TacticsFootball — lista zmian
=============================

Paczka PS Vita w deployu, osobny changelog Vity i strona POBIERZ pod /downloads
------------------------------------------------------------------------------
16.09.2026, 18:40

  • Tools/build-and-deploy.sh ma platformę vita, budowaną jako pierwsza (krok
    0): synchronizuje RELAY_GAMEPLAY_BUILD_UUID przez tools/sync-build-uuid.sh
    portu (i ostrzega, gdy nagłówek się zmienił i port wymaga commita),
    uruchamia build.sh portu, kopiuje build/TacticsFootball.vpk do
    dist/TacticsFootball-Vita.vpk, wysyła paczkę w tle i dopisuje wpis vita z
    rozmiarem do build-info.json pełnego wydania. Katalog portu wskazuje
    VITA_PROJECT (domyślnie ../tactics-football-vita); brak repozytorium, jego
    changelogu albo arm-vita-eabi-gcc przerywa run przed pierwszym buildem.
    Pełny run bez --only/--skip obejmuje teraz także Vitę; panel wysyłek ma
    osiem wierszy.
  • Port Vita ma własny changelog dla graczy
    ../tactics-football-vita/CHANGELOG-PLAYERS.md o tych samych zasadach co
    plik Unity; dotychczasowe punkty „Na PS Vita” z CHANGELOG-PLAYERS.md
    przeniesiono do niego bez prefiksu. Skrypt deployu formatuje go tym samym
    Tools/make-web-changelog.py do .changelog-vita.json przy każdym buildzie
    Vity, serwer zwraca go w /v1/downloads jako vitaChangelog, a strona
    POBIERZ pokazuje pod listą paczek osobną sekcję „CO NOWEGO NA PS VITA”.
    Lista paczek zna platformę vita (etykieta „PS Vita”, kolejność Windows,
    macOS, PS Vita). Instrukcje obu repozytoriów opisują podział changelogów.
  • Strona pobierania ma własny adres https://sianecki.pl/tf-lobby/downloads:
    nowa trasa GET /downloads renderuje stronę statystyk z otwartym panelem
    POBIERZ, statsPage przekierowuje stare /stats/downloads na ../downloads,
    menu nagłówka bierze adres z siteTab.Href(), a stats.js liczy adresy
    zakładek i aktywną zakładkę z uwzględnieniem /downloads.
    UpdateChecker.DownloadPageUrl w grze otwiera nowy adres zamiast
    stats#downloads. serverProtocolUUID nie jest podbity: nowe pole odpowiedzi
    jest addytywne, a klient Unity ignoruje nieznane pola.

Vita: powtórka gola, markery boiska, pasek komentarza i orientacja siatki
-------------------------------------------------------------------------
16.09.2026, 17:57

  • Powtórka gola po banerze GOOOL: dwa ujęcia jak w ReplayDirector.Play (1,85
    s i 1,5 s lotu, zamach 0,32 s, 2 s w siatce, 1 s na cieszynkę — łącznie
    ~9,4 s), oba z jedynej kamery z góry, żeby relay z Unity wychodził z
    powtórki w tym samym momencie. Piłka leci od nogi strzelca do wybranego
    pola bramki, zawodnicy stoją w pozycjach sprzed strzału. ✕, ◯ albo tap
    pomija resztę ujęć. Na czas powtórki znikają karty, kursor, selektor i
    komentarz; w lewym górnym rogu boiska miga duże „R” z podpisem POWTÓRKA
    (jak w MicroProse Soccer), na dole tylko „✕ POMIŃ”.
  • Filtr CRT podczas powtórki: src/crt.c odtwarza CrtReplay.shader nakładkami
    alpha (scanlines i grille z powtarzanego kafelka, ziarno, winieta,
    migotanie, przesuwający się pasek, dropouty taśmy) w ok. 1/3 siły shadera,
    bo nakładka nie może rozjaśnić obrazu jak shader.
  • Markery boiska rozdzielone znaczeniowo: złoty ring.png tylko pod stopami
    aktywnego zawodnika (puls alpha), czerwony pointer.png nad głową celu
    akcji (cel odbioru, właściciel piłki przy wskazanym polu odbioru, cel
    odbioru komputera podczas animacji), biały square.png na środku kafelka
    kursora (statyczny, szary nad polem niedostępnym). Usunięte narożniki
    wokół odbiorcy podania i pola bramki oraz stary pulsujący kursor.
    Kolejność: boisko → kursor pola → ring → cień → postać → piłka → pointer →
    HUD. Tekstury generuje tools/make-markers.py z reference/ui.
  • Siatka rysowana jak w Unity: y rośnie w górę ekranu (wiersz 0 na dole),
    więc ustawienie wyjściowe (obrońca w rowHigh u góry, pomocnik w rowLow u
    dołu) wygląda tak samo na obu platformach. D-pad, tap i kolejność
    zasłaniania postaci przeliczone.
  • Pasek komentarza: podpowiedź „co teraz” usunięta, komentarz wyśrodkowany
    na całej szerokości w rozmiarze 15; nazwiska i nazwy obu reprezentacji
    pogrubione, o punkt większe i w kolorze interfejsu stroju (port
    GameHud.FormatMatchCommentary), reszta tekstu złota. Podpowiedzi
    przycisków dosunięte do lewej i do dolnej krawędzi, SELECT · MENU przy
    prawej.
  • Karta zawodnika i panel akcji dosunięte do krawędzi ekranu (4 px od
    boiska); karta ma wysokość liczoną z zawartości z tym samym dolnym
    marginesem co panel „TWOJA TURA”, separator pod paskami tylko gdy są
    flagi.
  • Lista akcji otwiera się od razu, gdy jest do wyboru podanie, strzał, lob
    albo odbiór; ruch startuje automatycznie tylko bez piłki i bez odbioru w
    zasięgu. Na początku tury kursor staje na zawodniku najbliżej piłki.
  • Na górnym pasku „TURA:” pokazuje pseudonim z opcji zamiast „GRACZ”; ciemny
    pasek rozszerza się do długości tekstu.
  • deploy.sh przez USB pokazuje pasek postępu kopiowania (obserwuje rozmiar
    pliku docelowego), pull-core.sh ściąga ostatni core dump z konsoli.
  • Port ma własne CLAUDE.md z zasadami commitowania, changeloga i zgodności z
    Unity, przepisanymi z tej instrukcji.

Build na iPhone'a: eksport Xcode i profil iPada dla tłumu i interfejsu
----------------------------------------------------------------------
16.09.2026, 13:40

  • Tools/build-and-deploy.sh ma nową platformę iphone: zaraz po eksporcie
    iPadOS (ios) eksportuje z tego samego celu Unity osobny projekt Xcode
    tylko na iPhone'a do Build/iPhone, ze zmianą nazwy na
    TacticsFootball-iPhone.xcodeproj i tymi samymi poprawkami schematów co
    pozostałe eksporty Apple. Plik .ipa nadal buduje się ręcznie w Xcode; nic
    nie jest pakowane ani wysyłane. Pełny run bez --only/--skip obejmuje teraz
    iPadOS, iPhone, macOS, Windows i tvOS; wpis ios w metadanych pozostaje
    jeden, bo klient zgłasza się jako ios na obu urządzeniach.
  • BuildScript.Build czyta zmienną BUILD_APPLE_DEVICE (iPad/iPhone) i na czas
    jednego eksportu iOS ustawia PlayerSettings.iOS.targetDevice, a po
    buildzie przywraca wartość z projektu, żeby tryb wsadowy nie zapisał do
    ProjectSettings.asset celu iPhone. Bez zmiennej ustawienie projektu
    pozostaje nietknięte.
  • iPhone dostaje ten sam zredukowany profil widowni co iPad i tvOS: 333
    kibiców zamiast 666 i odświeżanie póz 6 Hz.
    StadiumCrowd.ResolvePlatformProfile rozpoznaje teraz cały
    RuntimePlatform.IPhonePlayer bez sprawdzania modelu urządzenia, a
    PreparedStadiumBaker wypieka zredukowany prefab tłumu dla każdego buildu
    iOS, niezależnie od targetDevice.
  • Układ dotykowy interfejsu (UiSupport.UsesLargeTabletLayout) obowiązuje na
    każdej platformie mobilnej, nie tylko przy viewportcie iPada: iPhone ma te
    same większe przyciski menu i HUD-u, podbite małe czcionki i skrócony
    panel opcji bez wiersza wibracji pada. Klucz priorytetu przekaźnika
    pozostaje ipad dla obu rodzin urządzeń.

Przygotowanie meczu podczas prezentacji VS i wybierania drużyn
--------------------------------------------------------------
16.09.2026, 12:07

  • Karty VS pojawiają się od razu, a pełny obrót kamery trwający sześć sekund
    zaczyna się po przejęciu gotowego świata i ustawieniu piłki. Czas
    oczekiwania nie zużywa animacji; po obrocie karty schodzą w 0,72 s, pod
    warunkiem gotowości grywalnego meczu.
  • Pełnoekranowe tło prezentacji VS zaczyna z alfą 1 i podczas całego
    sześciosekundowego obrotu kamery przechodzi krzywą SmoothStep do
    dotychczasowej alfy 0,87. Karty i efekty pozostają widoczne, a stadion
    stopniowo wyłania się z czerni wraz z doczytywaną widownią. Usunięto
    omyłkową dodatkową warstwę splasha nakładaną na menu po starcie gry.
  • Neutralna baza stadionu, terenu i panoramy jest automatycznie wypiekana do
    lekkiego PreparedStadium, a rozmieszczona widownia, szkielety i siatki LOD
    do osobnego PreparedCrowd. Pierwszy prefab zawiera tylko kilka zbiorczych
    siatek krzyżujących się kart z małą teksturą sylwetki, pogrupowanych
    według przynależności i barwy; zachowuje więc zapełnione trybuny podczas
    obrotu 360° bez deserializacji setek Animatorów. Pełna widownia jest
    ładowana oraz instancjowana asynchronicznie z budżetem integracji 2 ms na
    klatkę, poza kadrem dostaje materiały, grafy animacji, szaliki i LOD, a
    jej sylwetki są włączane porcjami pod widocznym impostorem. Karty znikają
    dopiero po ukończeniu podmiany. Baker utrwala proceduralne materiały i
    sprawdza oba prefaby pod kątem brakujących skryptów oraz pustych slotów.
    Wygenerowane pliki pozostają lokalnym, odtwarzalnym wejściem buildu i nie
    trafiają do repozytorium. Brak lub niezgodna wersja lekkiego prefabu
    uruchamia dotychczasowy generator jako fallback edytora.
  • Trwały cache rozpoczyna pracę po wyborze reprezentacji w menu. Wczytuje
    zasoby obu strojów, przejmuje wypieczoną bazę świata, przygotowuje boisko
    i osiem modeli wybranych zawodników. Gotowa aktywna hierarchia czeka poza
    kadrem i jest odsłaniana w lokalnym meczu bez ponownego tworzenia lub
    jednoczesnego włączania setek obiektów.
  • Cztery układy koszenia murawy są prebuildowane wraz z bazowym światem.
    Zmiana drużyny przełącza gotowy wariant, przemalowuje istniejące modele
    kibiców, szaliki i pasy siatek porcjami po 2 ms, odbudowuje wyłącznie
    lekkie bannery, flagi oraz czterech zawodników zmienionej strony. Dwa
    gotowe atlasy albedo widowni 512 px są teraz częścią bake'a, więc świeży
    proces nie musi osobno ładować ich źródłowych assetów przed nałożeniem
    barw. Nie przelicza ponownie terenu, panoramy, trybun, kolizji miejsc ani
    333/666 animowanych widzów; niezmieniona drużyna zachowuje swoje gotowe
    modele. Klikanie selektora podczas pierwszego prebuilda zapamiętuje tylko
    najnowsze barwy i nie wyrzuca częściowo zbudowanej bazy.
  • Cache świata pozostaje własnością trwałego preloadera także podczas
    lokalnego meczu. Powrót do menu parkuje tę samą hierarchię, czyści
    znaczniki, linie, siatki bramek i ślady wślizgów, przywraca spokojną
    widownię oraz odświeża wyłącznie osiem modeli zawodników na już
    wygenerowanych atlasach. Kolejny mecz tej samej pary nie buduje ponownie
    stadionu ani 666 kibiców.
  • Menu zachowuje ostatnią parę reprezentacji, gdy istnieje ich gotowy świat.
    Automatyczny powrót do drużyny ulubionej działa nadal po świeżym
    uruchomieniu oraz po ścieżce bez lokalnego cache, ale nie unieważnia już
    stadionu przy zwykłym rewanżu.
  • Ścieżki sieciowe i powtórki zachowują etapową budowę oraz widownię
    dodawaną od LOD3, ponieważ ich skład i ziarno nie wynikają z lokalnego
    selektora.
  • Budowanie boiska, stadionu, terenu i zawodników oddaje sterowanie między
    etapami. Tworzenie kilkuset kibiców oddaje klatkę po około 3 ms pracy,
    między pojedynczymi postaciami. Zachowano synchroniczne wejścia do
    przebudowy w edytorze.
  • Domyślny tekst interfejsu korzysta z JetBrains Mono, tak jak komentarz;
    Bagipay został usunięty z zasobów gry i nie jest już wybierany przez kod.
    Odrębne fonty tytułu i nagłówków pozostają bez zmian. Ekran technicznego
    ładowania pozostaje tylko dla powtórek i jako obsługa błędu z powrotem do
    menu.

  Poprawki:
  • Muzyka menu nie jest niszczona przy przejściu do meczu: jej źródło i
    tymczasowy listener przechodzą przez ładowanie, następnie muzyka wygasa
    wraz z wejściem motywu meczu. Nagranie 4096×2304 z 16 września
    potwierdziło, że poprzednia wersja jedynie rozłożyła budowę świata pod
    prezentacją i nadal zatrzymywała jej klatki; lokalny start przejmuje teraz
    prebuild wykonany w menu.
  • Pierwszy build gracza doszedł do wypiekania prefabu, lecz został
    zatrzymany przez 124 oczekiwane odrzucenia kolizyjnych miejsc zapisane
    jako błędy oraz katalog LOD umieszczony w pliku o innej nazwie niż jego
    klasa. Bake pomija teraz te miejsca bez błędu, każdy serializowany typ ma
    własny zgodnie nazwany plik, a prefab jest sprawdzany pod kątem
    brakujących skryptów. Drugi build potwierdził poprawne skrypty, lecz
    ujawnił 687 pustych referencji proceduralnych materiałów oraz nadal
    kosztowne przetwarzanie atlasów i uruchamianie animacji po restarcie;
    materiały są teraz zbierane bezpośrednio z rendererów i utrwalane, a te
    prace przeniesiono do bake'a albo tła. Kolejna próba ujawniła, że tekstura
    impostora traciła dane CPU przed skopiowaniem do trwałego assetu;
    pozostaje teraz czytelna do zakończenia bake'a, a brak kopii kończy
    generowanie jednoznacznym błędem. Ponowna weryfikacja statyczna przez
    csharp-ls nie zgłasza diagnostyk; następny build i rzeczywisty czas
    przygotowania cache wymagają sprawdzenia w Unity.

Vita: górny HUD zgodny z tablicą Unity
--------------------------------------
16.09.2026, 07:25

  • Górny pasek Vity używa płaskich pól w kolorach aktualnych strojów i tych
    samych herbów co Unity. Kontrast nazw jest dobierany według tego samego
    progu; Argentyna używa błękitu pasów koszulki.
  • Ekran wyniku ma ciemną siatkę, ramkę, złote cyfry JetBrains Mono oraz czas
    MM:SS z zegara statystyk meczu. Zachowano wysokość paska, oznaczenie
    aktywnej drużyny oraz miejsca na rundę, turę i powtórkę.
  • Pola rundy i tury są równymi, półprzezroczystymi pasami przepuszczającymi
    barwę drużyny, bez dodatkowej ramki wewnątrz pola tury. Tekst jest
    centrowany w obu osiach względem własnego pola, a pozycja pionowa wynika z
    wysokości glifów.
  • Porównano 14 herbów i font Mono z Unity bajt po bajcie. Weryfikacja przez
    odczyt kodu, bez budowania i uruchamiania portu.

Płaski dolny HUD z ekranem wyniku i zegarem
-------------------------------------------
16.09.2026, 06:59

  • Dolna tablica wyników ma dwa płaskie pola w barwach grających drużyn,
    herby używane na strojach zamiast flag oraz kontrastowe nazwy dopasowujące
    się do dostępnej szerokości. Usunięto plastikowy połysk i wypukłą ramkę
    wyniku.
  • Akcent Argentyny w interfejsie pochodzi z koloru pasów koszulki (Trim),
    czyli błękitu #7ED2EB w stroju domowym; panel wyniku i komentarz nie
    używają białego tła koszulki. Strój wyjazdowy zachowuje swój niebieski
    akcent.
  • Centralny wynik używa JetBrains Mono na ekranie z drobną siatką, ramką i
    delikatną poświatą cyfr. Pod wynikiem widnieje czas MM:SS z istniejącego
    zegara statystyk meczu. Zachowano miganie cyfry po golu i widoczność
    podczas powtórek.
  • Płaski pasek komentarza ma cienkie linie i szerokie ukośne pasy przy
    bokach, poza obszarem tekstu. Przy zmianie posiadania przyjmuje barwy
    drużyny z piłką i ponownie dobiera kontrast wyróżnionych nazwisk;
    zachowuje odwracanie kolorów po golu. Dłuższe teksty dopasowują rozmiar do
    wysokości paska.
  • Tablica wyników jest niższa (60 zamiast 72 jednostek), podobnie pasek
    komentarza (38 zamiast 46). Plakietka i akcje zachowują odstęp 16
    jednostek; obszary kamer meczu i powtórki uwzględniają nową wysokość
    tablicy.
  • Weryfikacja statyczna przez csharp-ls; bez uruchamiania Unity. Wygląd na
    iPadzie wymaga sprawdzenia w grze.

Szersza plakietka zawodnika i równe marginesy HUD
-------------------------------------------------
16.09.2026, 06:10

  • Plakietka zawodnika ma szerokość 400 zamiast 360 jednostek, z odpowiednio
    przesuniętą kolumną akcji. Panel sieciowy, menu i plakietka mają jednakowy
    margines 16 jednostek od bocznych krawędzi; górne panele zachowują taki
    sam odstęp od góry, a plakietka i akcje od paska komentarza.

  Poprawki:
  • Pole wartości statystyki jest szersze (64 zamiast 30 jednostek), dzięki
    czemu 10/10 nie nachodzi na kolorowy pasek umiejętności, również w
    układzie iPada.

Debug sieci domyślnie ukryty
----------------------------
16.09.2026, 06:08

  • Panel diagnostyczny sieci w lewym górnym rogu jest domyślnie ukryty.
    Pierwsze naciśnięcie F9 pokazuje panel, a kolejne ponownie go ukrywa.

C64: kolor szansy jak w Unity i linia podania
---------------------------------------------
15.09.2026, 20:20

  • Port C64: szansa podania, strzału i loba w HUD ma kolor jak
    BoardView.SuccessChanceColor w Unity (czerwony < 20 %, pomarańcz, żółty,
    zielony, jasnozielony > 80 %), a przy wyborze odbiorcy na boisku rysuje
    się linia podania — kropki na polach między piłką a odbiorcą w kolorze
    szansy (kafle wielokolorowe mają kolory 0–7, więc zielenie idą w cyjan,
    pomarańcz w czerwień; dwa ostatnie wolne kafle zestawu, pola liczone w
    asemblerze pass_line.s). Zawodnik po zakończonej aktywacji ma ciemniejszy
    odcień stroju. Rodzaj pudła losuje xorshift zamiast 32-bitowego hasha FNV
    (C64 nie jest authority; oszczędność ~350 B), komunikaty meczu i ekranu
    sieci skrócone, żeby to zmieścić.

C64: koniec migania sprite'ów i drgania HUD w meczu, aktywny zawodnik pod boiskiem
------------------------------------------------------------------------------
15.09.2026, 19:10

  • Port C64: pod boiskiem wisi aktywny zawodnik z numerem („LEWANDOWSKI #9”),
    a bez wyboru „WYBIERZ ZAWODNIKA”; numer jest doklejany do nazwiska już w
    generatorze danych (tools/gen-teamdata.py, skracanie: inicjał → samo
    nazwisko → obcięcie, żeby zmieścić 14 znaków), więc widać go też w HUD;
    czcionka dostała #.

  Poprawki:
  • Port C64: granica HUD/boisko (i inne paski zmieniające tryb lub tło)
    drgała o 1–2 linie z ramki na ramkę przez opóźnienie przerwania rastrowego
    (badline, długa instrukcja). Pasek jest teraz ustawiany 3 linie wcześniej,
    kolory dodatkowe trybu wielokolorowego idą od razu (w wierszach hires
    niewidoczne), a tryb, mapa pamięci i tło są zapisywane w wygaszaniu
    poziomym ostatniej linii poprzedniego wiersza.
  • Port C64: gdy obsługa zdarzenia rastrowego trwała dłużej niż odstęp do
    następnego (przepisanie kilku obiektów multipleksera, np. sześciu
    sprite'ów nazwiska w ramce, to kilkanaście linii), przerwanie ustawiało
    $D012 na linię, która już minęła, i czekało na nią do następnej ramki —
    gubiąc otwarcie ramki dolnej i start ramki z nowymi pozycjami. Przy 16
    obiektach (zawodnicy, piłka, kursor, tekst) co druga ramka pokazywała
    tylko sprite'y z końca listy: mecz migał, a w fazie wskazywania pola widać
    było dwóch zawodników. Przerwanie sprawdza teraz, czy linia następnego
    zdarzenia już minęła, i wtedy wykonuje je od razu.

C64: joystick w obu portach i wybór sterowania w opcjach
--------------------------------------------------------
15.09.2026, 18:05

  • Port C64 (../tactics-football-c64): w opcjach jest STEROWANIE — domyślnie
    joystick, do wyboru klawiatura; ustawienie trafia do TF.CFG (wersja pliku
    2, dodatkowy bajt). W trybie joysticka z klawiatury czytany jest wyłącznie
    RUN/STOP (pełny skan matrycy widziałby joystick z portu 1 jako klawisze:
    dół = RETURN i W, lewo = A i kursor w prawo), w trybie klawiatury
    joysticki są ignorowane. make joytest buduje osobny program diagnostyczny
    pokazujący na żywo $DC00/$DC01 i odczyt sterownika.

  Poprawki:
  • Port C64: joystick w porcie 1 dawał pomieszane sygnały (jego linie na
    $DC01 wyglądały dla skanera matrycy jak klawisze RETURN, W, A, kursory).
    Sterownik czyta teraz oba porty wprost (port 2 z $DC00, port 1 z $DC01
    przy wszystkich wierszach matrycy w stanie wysokim) i składa je razem,
    więc joystick działa w dowolnym porcie. Skos drążka (obie osie naraz,
    typowe przy pchnięciu w bok) nie jest nowym kierunkiem: zostaje oś
    trzymana już w poprzedniej ramce, inaczej wejście czeka na jedną oś —
    koniec z przypadkową górą/dołem przy ruchu w bok. W wyborze drużyn „w
    lewo" na liście gospodarzy nie wraca już do głównego menu (tylko
    RUN/STOP), bo pchnięcie w bok wyglądało jak Escape.

Spójna karnacja głowy i odsłoniętego ciała
------------------------------------------
15.09.2026, 12:46

  Poprawki:
  • Atlasy zawodników z pola zapisują na wyspach skóry dokładnie kolor
    karnacji zawodnika, zgodny z ciągłą bryłą ciała: twarz nie zachowuje
    pomarańczowego tła źródłowego, a stroje nie używają zastępczej karnacji.
    Dotyczy to również RGB przezroczystych pikseli mieszanych przy
    filtrowaniu, a cache rozróżnia odcienie skóry.
  • Materiały wycinające twarz i stroje włączają _AlphaToMask, zgodnie z
    konfiguracją nieprzezroczystych masek URP dla MSAA. Kolor przedłużanych
    spodenek i getrów nie zależy od jasności skóry pod nimi.
  • Weryfikacja statyczna: diagnostyka dokumentu przez csharp-ls bez uwag;
    konfiguracja porównana z lokalnym kodem URP i dokumentacją Unity
    6000.6.0f1. Bez uruchamiania gry; wygląd wymaga sprawdzenia w Unity.

Wzór koszenia murawy z ziarna meczu wspólny dla Unity, Vity i C64
-----------------------------------------------------------------
14.09.2026, 17:15

  • Bramka /c64 dokłada do linii T|<kitA>|<kitB>|… trzecie pole: wzór koszenia
    murawy 0..3 liczony z ziarna meczu w nagłówku TFMATCH2 tak samo jak
    BoardView w Unity (dodatnia reszta z dzielenia przez cztery), bo C64 nie
    ma miejsca na parsowanie 32-bitowego ziarna; nicki gospodarza i gościa
    przesunęły się na pola 4 i 5 (klient C64 ich nie czyta). Kontrakt /v2 bez
    zmian, UUID bez zmian.
  • Port PS Vita (../tactics-football-vita): murawa z trzech tekstur trawy
    Unity (PitchGrassLight/Medium/Dark) i cztery wzory PitchPattern
    (jednolity, pasy poprzeczne po dwa wiersze, pasy podłużne po dwie kolumny,
    szachownica z trzech tonów) rysowane tą samą regułą co
    BoardView.BuildPitchPattern; wzór wybiera ziarno meczu (((seed % 4) + 4) %
    4) — lokalnie z kickoff_seed(), w meczu przez relay z pola 5 nagłówka
    TFMATCH2, więc obie strony widzą to samo boisko.
  • Port C64 (../tactics-football-c64): te same cztery wzory jako raster
    jasnej zieleni w rozjaśnionych polach; wzór to ziarno meczu mod 4, a w
    meczu sieciowym wartość z linii T. W pamięci jest jedna spakowana mapa
    wzoru jednolitego (66 kafli) i dla 42 kafli, które któryś wzór rozjaśnia,
    bliźniak z rastrem (108 kafli razem); procedura pitch_pattern.s po
    rozpakowaniu mapy podmienia kafle w rozjaśnionych polach na bliźniaki, a
    podświetlenie zasięgu dobiera tło po kaflu pod sobą. Zestaw znaków zajął
    dotychczasowy „ogon” z buforami, więc bufory zapisywane przed odczytem
    (kafle pod podświetleniami, lista pokojów, lokalne AI, geometrii, ruchu i
    akcji) przeniosły się do kilobajta zwalnianego przez title_stash()
    (STASHBSS), co zostawia ok. 450 B wolnego w segmencie kodu.

Commodore 64 gra przez relay: bramka tekstowa /c64 i klient na WiC64
--------------------------------------------------------------------
13.09.2026, 15:40

  • Serwer ma bramkę /c64/* (c64gateway.go) dla portu na Commodore 64: WiC64
    umie tylko GET z adresem, bez nagłówków, JSON-a i kodu HTTP, więc handlery
    rooms, create, join, poll, cmd, setup, done i leave budują z parametrów
    zapytania syntetyczne żądania do /v2 w tym samym procesie (httptest, z
    przekazanym adresem klienta do limitów) i oddają tekst: linie \n, pola |,
    tylko ASCII, pierwsza linia OK|… albo ERR|kod, zawsze HTTP 200. Sesja,
    peer i sekret krążą w parametrach; game_result jest rozkładany na płaskie
    linie E|R|… (rewizja, faza, prezentacja, rodzaj, flagi i wynik attemptu),
    T|… (kity i nicki z TFMATCH2), S|… (pola bloku STATE) i osiem P|…
    zawodników, a poll oddaje najwyżej m eventów i cofa lastSeq do ostatniego
    oddanego, bo bufor C64 ma ok. 500 B. Platforma c64 ma jawnie priorytet 0 —
    nigdy nie liczy przy Unity albo Vicie. Bramka opisana w
    server/lobby/README.md i .ai/RELAY-MULTIPLAYER.md; multiplayerProtocolUuid
    bez zmian (kontrakt /v2 nietknięty).
  • Port C64 (../tactics-football-c64): sterownik WiC64 przez port użytkownika
    (wic64.c: protokół R, HTTP GET z URL po ASCII, odczyt statusu i długości,
    działa też w VICE z -userportdevice 23), klient relay.c (lista pokojów,
    tworzenie/dołączanie, poll, komendy, setup, potwierdzenie prezentacji,
    wyjście; adres i UUID buildu w netconfig.h generowanym z
    NetworkCompatibility.cs), po tytule jest główne menu w stylu Sensible
    Soccer (belki MECZ Z KOMPUTEREM / GRA SIECIOWA / OPCJE między
    zawodnikami), dopiero potem wybór drużyn — w sieci tylko własnej,
    przeciwnika wybiera drugi gracz; OPCJE to ulubiona reprezentacja
    (domyślnie zaznaczana jako gospodarz i moja drużyna w sieci) i pseudonim
    do gry sieciowej wpisywany joystickiem, zapisywane w pliku TF.CFG na
    stacji przez KERNAL (własne wrappery w asemblerze) i wczytywane przy
    starcie i ma ekran pokojów (net_view.c), a w meczu każda akcja jest
    komendą przez relay i stan jest przywracany z wyniku authority
    (match_view.c: faza oczekiwania na sieć, tekst w ramce o właścicielu
    piłki). Odpowiedzi bramki są tłumaczone z ASCII na PETSCII przy odbiorze
    (cc65 trzyma literały 'O', '|', '\n' w PETSCII). Pamięć przebudowana, żeby
    zmieścić bufory sieciowe i opcje (LOWBSS/LOWBSS2/TAILBSS, bufory rastra w
    ogonie obszaru sprite'ów, klatki tekstu w ramce pod KERNAL-em, spakowany
    ekran tytułowy ładowany w miejsca zajmowane dopiero po starcie i odkładany
    do RAM pod I/O, generator xorshift16 zamiast 32, .assert na kolizję BSS).
    Przepływ lista → pokój → dołączenie fałszywej Vity → setup sprawdzony w
    VICE z emulowanym WiC64 na wdrożonym serwerze. Ograniczenia: C64 nigdy nie
    jest authority, jeden event na odpytanie, losowy clientId na uruchomienie,
    bez reconnectu po restarcie.

Wspólne dane reprezentacji w JSON i pierwszy etap portu na Commodore 64
-----------------------------------------------------------------------
13.09.2026, 08:45

  • Dane reprezentacji i zawodników wydzielone z kodu do Data/teams.json —
    jednego źródła prawdy wspólnego dla Unity i portów: id, polska nazwa,
    trzyliterowy skrót, siła, cztery osie stylu z komentarzem, rola gwiazdy,
    komplety strojów (domowy i wyjazdowy: koszulka, wykończenie, spodenki,
    getry, bramkarz, rodzina koloru) oraz czterech zawodników z rolą,
    nazwiskiem, wzrostem, odcieniem skóry, numerem, nogą i sześcioma
    umiejętnościami. Schemat opisuje Data/README.md.
  • Tools/gen-team-data.py generuje z JSON-a blok TeamStrengths + Definition w
    NationalTeams.cs między znacznikami BEGIN/END generated (treść bajt w
    bajcie taka jak dotąd, więc bez zmiany balansu ani UUID), a w trybie
    --check pilnuje, żeby kolory strojów (HomeKit/AwayKit, palety bramkarzy) i
    kolejność enuma NationalTeam, które zostają w C#, zgadzały się z JSON-em.
    .ai/PROJECT-INSTRUCTIONS.md i .ai/GAMEPLAY-RULES.md §13 mówią, że liczby
    zmienia się w JSON-ie, nie w C#.
  • Port na Commodore 64 w osobnym repozytorium ../tactics-football-c64 (cc65:
    C + ca65, make, make run w VICE), na wzór ../tactics-football-vita; czyta
    projekt Unity przez UNITY_PROJECT i ma własny tools/gen-teamdata.py, który
    z tego samego JSON-a robi tablice bajtów dla 6502 (nazwy i nazwiska w
    kodach ekranowych, umiejętności 0-100, styl −100..100, kolory C64 dobrane
    do strojów z pominięciem zieleni murawy i czerni konturu, rodziny kolorów
    do reguły kolizji, kolejność alfabetyczna menu jak NationalTeams.All).
    Etap 1 daje: ekran tytułowy (logo z tęczą rastrową, powiększeni
    zawodnicy), menu wyboru gospodarzy i gości z podglądem strojów w doborze
    jak KitsForMatch (kolizja rodzin kolorów → strój wyjazdowy gościa), start
    meczu i statyczny ekran meczu 4 na 4: boisko 18×12 pól po 16 px na jednym
    ekranie z bramkami na 6 pól i polem karnym 4×7,2 pola wprost z reguł,
    ustawienie startowe z MatchFactory, piłka przy napastniku drużyny A, HUD z
    nazwami w kolorach strojów i wynikiem 0:0. Boisko to tryb wielokolorowy
    znaków z kaflami generowanymi z obrazu (77 kafli), zawodnicy to sprite'y
    wielokolorowe wysokości mniej więcej jednego pola, a 9 obiektów na 8
    sprite'ów sprzętowych obsługuje multiplekser oparty o listę zdarzeń
    rastrowych (raster.c + raster_irq.s). Wejście: joystick w porcie 2 i
    klawiatura czytana z matrycy (kursory/WASD, RETURN/SPACJA, RUN/STOP). Bez
    rozgrywki, tur, AI, dźwięku i sieci; architektura rozdziela game/, data/,
    input/, render/ i wygenerowane dane, żeby następny etap dołożył siatkę
    ruchu i tury bez przepisywania fundamentu.

PS Vita jako klient relay, bariera prezentacji i pełne wyniki w Unity
---------------------------------------------------------------------
12.09.2026, 19:35

  • Serwer relay (/v2) prowadzi barierę PRESENTATION: /result z
    phase=PRESENTATION otwiera prezentację (presentationId, wymagane =
    połączone peery, termin 45 s), nowy POST
    /v2/sessions/{id}/presentation/done to potwierdzenie, które nie jest akcją
    meczu (nie trafia do authority, nie rusza revision) i emituje
    presentation_done; gdy wszyscy wymagani, wciąż połączeni peery potwierdzą,
    minie termin albo kolejny wynik ją zastąpi, serwer wraca do INPUT i
    emituje presentation_finished (reason: all_ready/timeout/superseded).
    Snapshot niesie presentation. Peer, który wypadł, nie jest oczekiwany.
  • Bezpieczna re-elekcja authority: powrót lepszego peera niczego nie zmienia
    w trakcie prezentacji ani rozstrzygania; serwer robi rebalance wyłącznie
    na granicy PRESENTATION → INPUT albo po przyjęciu /result bez prezentacji.
    Klienty (Unity i Vita) po authority_changed wysyłają ponownie własną
    niezakończoną komendę, bo stary authority jej nie rozstrzygnie.
  • Obsługa gry sieciowej jak w Unity, bez kodów dla gracza: GET /v2/sessions
    zwraca pokoje czekające na drugiego gracza (nazwa, gospodarz, platforma,
    drużyna, limit goli, build), a POST /v2/sessions przyjmuje
    roomName/team/goalLimit z tą samą walidacją co /v1/games; joinCode
    pozostaje wyłącznie uchwytem przekazywanym z listy do /join. Menu gry
    sieciowej Unity zachowuje układ (lista pokojów, profil, STWÓRZ POKÓJ), ale
    listę bierze z relayu, „UTWÓRZ I CZEKAJ” publikuje pokój na relayu i czeka
    na peer_joined, „DOŁĄCZ ▸” dołącza przez relay; pasek deweloperski z kodem
    usunięty, ścieżka P2P (StartHostingP2P, NAT, /v1) zostaje w kodzie bez
    przycisku. Vita ma ten sam ekran: lista pokojów, UTWÓRZ I CZEKAJ, drużyna,
    limit goli, pseudonim; ekran pokoju gospodarza bez kodu.
  • Capabilities peera w create/join (replayPlayback, matchStatsPresentation,
    goalClipUpload; nieznane odrzucane) przechowywane w peers i peer_joined.
    Unity deklaruje replay i upload, Vita kartę statystyk. Właściciel uploadu
    klipów i raportu to peer z goalClipUpload (twórca, gdy obaj) —
    RelaySession.UploadOwnerPeerId, nigdy platform. multiplayerProtocolUuid
    podbity (nowe pola, endpoint i eventy); serverProtocolUUID i
    GameplayBuildUUID bez zmian.
  • Unity: RelayResultEvent niesie spłaszczone PassAttempt, TackleAttempt i
    ShotAttempt (wyniki, szanse, luźna piłka, rodzaj pudła, rykoszet, rodzaj
    gola); RelayMatchLink.ResultFrom odtwarza z nich CommandResult, więc
    PresentPass/PresentTackle/PresentShot i ReplayDirector działają bez
    przeliczania. Przez relay idą już wszystkie komendy (także podanie,
    odbiór, strzał, lob, cofnięcie). Authority publikuje PRESENTATION dla
    podania/odbioru/strzału/loba i FINISHED po końcu meczu; potwierdzenie
    wysyłane jest, gdy kontroler jest znów bezczynny (po replayu),
    IMatchLink.WaitingForPeers blokuje wejście do presentation_finished z
    komunikatem „Oczekiwanie na przeciwnika…”. Mecz relay wysyła raport i
    klipy z jednego peera (właściciel uploadu). Klient relay raportuje na iOS
    platformę ipad (build jest iPad-only).
  • PS Vita (../tactics-football-vita): klient /v2 na libcurl/mbedTLS w dwóch
    wątkach (zaparkowany long poll + krótkie żądania), gotowe odpowiedzi przez
    kolejkę do pętli głównej, stan meczu zmieniany wyłącznie w pętli;
    weryfikacja TLS przeciwko dołączonemu ca-bundle.pem (ISRG Root X1/X2)
    także dla statystyk, bez wyłączania weryfikacji. Stan sesji
    (relay_session.c: sessionId, joinCode, peerId, authorityPeerId, lastSeq,
    revision, phase, connection
    DISCONNECTED/CONNECTING/CONNECTED/RECONNECTING/FAILED; sekret tylko w
    transporcie). Menu GRA LOKALNA / GRA SIECIOWA z przeglądarką pokojów jak w
    Unity (UTWÓRZ I CZEKAJ, dołączenie z listy, drużyna, limit goli, pseudonim
    z systemowej klawiatury); ekran pokoju z nazwą, nickami A/B i statusem.
    Adapter relay_snapshot.c tłumaczy TFMATCH2 i STATE|… na MatchState i z
    powrotem oraz liczy tę samą sumę kontrolną co
    NetworkRules.ComputeChecksum. W meczu każdy przycisk to komenda przez
    relay (lokalne reguły tylko do podglądów i wstępnej walidacji), wynik
    authority przywraca stan i jest odgrywany z attemptów bez losowania;
    rozjazd sumy kontrolnej wymusza resync. Karta statystyk w PRESENTATION
    (akcja, zawodnik, szansa, wynik, wynik meczu,
    strzały/celne/podania/odbiory/posiadanie z lokalnego portu MatchStatistics
    karmionego autorytatywnymi wynikami), potwierdzenie po 2,4 s i oczekiwanie
    na presentation_finished. Reconnect z overlayem „PONOWNE ŁĄCZENIE…” i
    snapshotem bez odgrywania historii. Failover: gdy serwer wskaże Vitę jako
    authority, komendy rozstrzyga ta sama logika reguł co w singleplayerze.
    Overlay techniczny pod START. tools/relaytest.sh (host) i
    tools/sync-build-uuid.sh.
  • Jawne wyjście z meczu: POST /v2/sessions/{id}/leave od razu oznacza
    miejsce jako rozłączone, emituje peer_left i w razie potrzeby przenosi
    authority — drugi gracz widzi rozłączenie natychmiast, nie po 60 s ciszy;
    Unity wysyła je przy niszczeniu sesji (powrót do menu), Vita blokująco
    przy opuszczaniu meczu. HUD Unity pokazuje ping także w meczu przez relay
    (ILatencyProbe: P2P mierzy ping–pong, relay czas GET /v2/sessions/{id} co
    5 s). Vita: pojedynczy zerwany long poll nie pokazuje już „PONOWNE
    ŁĄCZENIE…” (dopiero drugi z rzędu), a overlay techniczny podaje powód
    ostatniego resyncu (poll <status> / checksum a vs b) i ostatni błąd curl.
    Tools/relay-fake-vita.py weryfikuje TLS przez certifi albo systemowy
    /etc/ssl/cert.pem (Python z python.org nie ma własnych rootów).
  • Testy serwera: jawne wyjście (peer_left i authority bez czekania na
    timeout), lista pokojów (tylko wolne i żywe, bez sekretów, uchwyt z listy
    dołącza) i walidacja pokoju, capabilities, bariera (oczekiwanie na obu,
    timeout, zastąpienie, peer, który wypadł), rebalance tylko na granicy i po
    zwykłym wyniku. Testy Unity: attempty strzału/podania/odbioru przez JSON.
    go test, testy EditMode i test na sprzęcie uruchamia użytkownik; VPK
    zbudowany toolchainem VitaSDK (build/TacticsFootball.vpk), csharp-ls bez
    diagnostyki w zmienionych plikach C#.

Klient relay /v2 w Unity i rola SimulationAuthority (POC)
---------------------------------------------------------
12.09.2026, 16:50

  • Unity ma kompletnego klienta serwerowego relayu /v2/sessions (create,
    join, reconnect, GET, long poll events, command, result), osobnego od
    legacy /v1/games i P2P przez Netcode, które działają dalej bez zmian. Nowa
    warstwa Assets/Scripts/Game/Net/Relay/: RelayProtocol (osobny
    multiplayerProtocolUuid, DTO pod JsonUtility), RelayMultiplayerClient
    (HTTP; sekret peera trzymany w RelayCredentials, nigdy nie logowany),
    RelayEventStream (dokładnie jeden long poll after=lastSeq&wait=25, kolejny
    od razu po odpowiedzi także pustej, backoff przy utracie sieci,
    410/401/404 → /reconnect, przerwanie zaparkowanego requestu przy wyjściu z
    meczu), RelaySession (stan sesji: sessionId, joinCode, peerId,
    authorityPeerId, lastSeq, currentRevision, currentPhase, ostatni stan;
    IsSimulationAuthority = peerId == authorityPeerId, bez lokalnego wyboru
    authority ani sprawdzania platformy).
  • Role rozdzielone: IMatchLink opisuje, czego MatchController potrzebuje od
    meczu sieciowego; implementują go NetworkMatchLink (P2P, bez zmiany
    zachowania — subskrypcje GuestLeft/HostLeft przeniesione z kontrolera do
    linku) i RelayMatchLink. Kontroler nie odróżnia transportów; pojęcie „host
    = liczy” zniknęło z nowej ścieżki. W relayu twórca sesji gra Drużyną A,
    dołączający Drużyną B niezależnie od authority; authority stempluje
    drużynę komendy z fromPeerId.
  • POC gameplayu przez relay: SELECT_PLAYER, DESELECT, MOVE, END_TURN.
    SelectPlayer idzie przez serwer, bo zaznaczenie jest częścią kanonicznego
    MatchState (MOVE rusza zaznaczonego, walidacja authority to czyta, pole
    siedzi w LiveState i w sumie kontrolnej). Lokalny zamiar to tylko POST
    /command; authority po game_command używa istniejących zasad
    (MatchCommandProcessor.Validate/Apply, bez drugiego silnika), podnosi
    rewizję, buduje pełny snapshot i logiczny event i wysyła /result, po czym
    cofa własną replikę i — jak drugi peer — zmienia stan dopiero po odebraniu
    game_result (RestoreLiveState + PresentCommand, bez RNG i bez ponownego
    liczenia). Authority symuluje jedną komendę naraz; odrzucenie komendy to
    wynik kind:"rejected" z podniesioną rewizją. Nieprzeportowane akcje
    (podanie, strzał, odbiór, lob, cofnięcie) pokazują komunikat zamiast iść
    do sieci.
  • Snapshot stanu wykorzystuje istniejące reprezentacje zamiast nowej:
    koperta {revision, gameplayBuildUuid, setup, live}, gdzie setup to
    MatchSnapshot (TFMATCH2: skład, seed, kity, nicki), a live to
    MatchState.LiveState w nowym LiveStateCodec (blok STATE|… wyjęty z
    GoalClip, który teraz do niego deleguje bez zmiany formatu klipów). Nic ze
    sceny Unity nie jest serializowane. Kick-off: peery wysyłają setup
    (reprezentacja, limit goli, nick) po skompletowaniu sesji, authority
    tworzy mecz przez MatchFactory + NationalTeams.ApplyDefinition i publikuje
    go jako rewizję 1; każdy peer, authority też, buduje scenę z odebranej
    koperty (GameBootstrap.PrepareRelayMatch). RelaySession buforuje komendy,
    które dotrą przed sceną.
  • Reconnect/resync: po /reconnect link czyści kolejki, przywraca stan ze
    snapshotu, IMatchLink.StateReplaced → MatchController.OnStateReplaced
    ustawia pozycje, piłkę i tryb bez odgrywania historii.
    peer_timeout/peer_reconnected przeciwnika pokazują i chowają planszę
    rozłączenia (GameHud.HideDisconnectNotice).
  • Tymczasowy overlay deweloperski RelayDevOverlay (F9,
    RelayDevOverlay.Enabled): RELAY, SESSION, PEER, AUTHORITY LOCAL/REMOTE,
    AUTHORITY PEER, OPPONENT, SEQ, REVISION, PHASE, STATE; bez sekretu. Pasek
    „RELAY /v2 (DEV)” w menu gry sieciowej (edytor, development build,
    TF_RELAY_DEV=1): utworzenie sesji z kodem i dołączenie kodem;
    TF_RELAY_CLIENT_ID nadpisuje clientId dla dwóch instancji na jednej
    maszynie. Legacy menu i P2P nieruszone.
  • Tryb testowy bez Vity: Tools/relay-fake-vita.py tworzy sesję jako
    platforma vita, czeka na Unity, wypisuje wybrane przez serwer authority,
    wysyła setup, odbiera kick-off, w --auto wysyła SELECT + MOVE + END_TURN i
    drukuje każdy game_result z rewizją, aktorem, polem, sumą kontrolną i
    stanem; interaktywnie przyjmuje select/move/end/deselect/state.
  • Testy EditMode RelayStateTests: round-trip LiveStateCodec, niezmieniony
    format klipów, odtworzenie identycznego meczu z koperty po JSON (suma
    kontrolna, RNG, następny rzut), unia payloadu eventów i snapshot z
    lastState: null w JsonUtility. csharp-ls (rozwiązanie
    TacticsFootball.slnx) nie zgłasza diagnostyki w żadnym zmienionym pliku;
    Unity ani testów nie uruchamiano zgodnie z zasadami projektu. Opis
    formatów, decyzji i notatki do bariery prezentacji/replayów (zadanie 3) w
    .ai/RELAY-MULTIPLAYER.md.

Relay multiplayer /v2/sessions na serwerze Go
---------------------------------------------
12.09.2026, 15:41

  • Serwer lobby dostał równoległe API /v2/sessions — fundament serwerowego
    relay multiplayera. Serwer nie liczy rozgrywki: trzyma sesję dwóch peerów,
    wybiera SimulationAuthority, przekazuje komendy do authority, rozgłasza
    jego wyniki do obu peerów, pamięta currentRevision, currentPhase i ostatni
    snapshot lastState jako nieinterpretowany JSON oraz pozwala peerowi
    odzyskać miejsce po zerwaniu. Legacy /v1/games (P2P) pozostaje bez zmian i
    nadal obsługuje istniejące buildy.
  • Komunikacja live idzie przez long polling na istniejącym HTTPS/Caddy: GET
    /v2/sessions/{id}/events?after=&wait= odpowiada natychmiast, gdy są nowe
    eventy, w przeciwnym razie czeka do wait s (maks. 30) albo do pojawienia
    się eventu i zwraca pustą listę. Handler przedłuża WriteTimeout na czas
    oczekiwania. Udane polle, jak heartbeaty, nie trafiają do logu.
  • Nowy, niezależny multiplayerProtocolUUID opisuje kontrakt /v2;
    serverProtocolUUID (legacy /v1) nie jest ruszany. Zgodność zasad gry
    między peerami sprawdza istniejący GameplayBuildUUID — dołączenie z innym
    buildem, innym protokołem albo do pełnej sesji jest odrzucane.
  • Authority wybiera serwer z własnej mapy platforma→priorytet (macos/windows
    100, ipad/appletv 90, vita 10, inne 0), ignorując liczby od klienta; remis
    rozstrzyga niższy peerId. Wybór następuje przy dołączeniu drugiego gracza
    i po wygaśnięciu authority (60 s bez żadnego uwierzytelnionego żądania);
    peer wracający po przerwie nie odbiera authority temu, kto prowadził mecz.
    Każda zmiana emituje authority_changed.
  • Dwa osobne liczniki: seq transportu (każdy event relayu, także adresowany
    tylko do jednego peera; lastSeq w odpowiedzi to następne after) i revision
    gameplayu nadawana przez authority w POST /result, wymagana >
    currentRevision. POST /command może wysłać każdy peer — serwer pakuje
    payload w game_command wyłącznie dla authority. POST /result przyjmuje
    tylko authority, zapisuje rewizję, snapshot i opcjonalną fazę (LOBBY,
    INPUT, RESOLVING, PRESENTATION, FINISHED — bariera prezentacji dojdzie w
    kolejnym etapie) i emituje game_result do obu.
  • Reconnect: POST /v2/sessions/{id}/reconnect po stabilnym clientId (albo
    ponowny join z tym samym clientId) zwraca to samo miejsce z nowym
    peerSecret i pełnym snapshotem. Sekret porównywany w stałym czasie;
    nagłówki X-Peer-Id / X-Peer-Secret.
  • Limity i sprzątanie: 100 sesji, 10 na IP, 2 peerów, ciała 4 KiB / 16 KiB
    (komenda) / 128 KiB (state) / 32 KiB (event), bufor 256 eventów i 1 MiB na
    sesję (poniżej bufora 410 resync_required), sesja bez żywego peera znika
    po 5 min, każda po 12 h; reaper co 5 s. Błędy /v2 to JSON
    {"error","message"}.
  • main.go wydziela routes(), dzięki czemu testy stawiają cały router z /v1
    włącznie. Testy w multiplayer_test.go (do uruchomienia przez użytkownika,
    go test ./...) pokrywają tworzenie sesji, join code, limit peerów,
    niezgodny build i protokół, Mac > Vita niezależnie od twórcy, tie-break,
    routing komendy do authority, odrzucenie wyniku od non-authority i starej
    rewizji, kolejność seq, budzenie long polla, pusty poll po wait, bufor i
    resync, reconnect, zmianę authority po timeout, sprzątanie porzuconej
    sesji, scenariusz Definition of Done oraz niezmieniony kontrakt /v1/games.
    Go nie budowano ani nie testowano lokalnie zgodnie z zasadami projektu;
    gofmt niedostępny na maszynie.

Chmury i słońce ponownie widoczne nad panoramą
----------------------------------------------
04.09.2026, 07:19

  Poprawki:
  • Chmury, tarcza słońca i jej poświata są ustawiane za najdalszym punktem
    wygenerowanej panoramy zamiast na stałej odległości 200 jednostek od
    kamery. Poszerzenie terenu i odsunięcie pierścieni krajobrazu nie może już
    pozostawić billboardów nieba wewnątrz panoramy, a dalekie odcięcie
    aktywnej kamery uwzględnia również poświatę słońca.
  • Dolna krawędź każdej chmury zachowuje pięciojednostkowy margines nad
    najwyższą warstwą krajobrazu mierzony w obrazie aktywnej kamery.
    Wcześniejsze porównanie wysokości obiektów w świecie przy kamerze
    skierowanej w dół potrafiło wypchnąć cały zestaw chmur ponad górną krawędź
    kadru; nowa reguła działa tak samo dla zwykłego widoku, kamery stadionowej
    i powtórek.
  • Test regresji sprawdza jednocześnie, że całe chmury pozostają ponad
    panoramą w kadrze oraz że płaszczyzna słońca leży za każdym wierzchołkiem
    krajobrazu dla kamer ortograficznej i perspektywicznej. Analiza csharp-ls
    ładuje rozwiązanie bez diagnostyki dotyczącej zmienionych plików; zgłasza
    jedynie istniejące ostrzeżenia obszaru roboczego o referencjach metadanych
    projektów. Unity ani testów nie uruchamiano zgodnie z zasadami projektu,
    dlatego wygląd należy potwierdzić w scenie z kamer gry.

Adaptacyjny LOD kibiców i rekwizytów według wielkości na ekranie
----------------------------------------------------------------
01.09.2026, 11:13

  • Każdy posadzony kibic dostaje poziom geometrii wybierany z jego
    rzeczywistej wielkości na ekranie, a nie z odległości od kamery. Mierzona
    jest długość rzutu własnej osi pionowej postaci — od stóp do czubka głowy
    — przez aktywną kamerę, w pikselach, które ekran naprawdę rysuje, więc
    zmiana kąta ani zoomu nie psuje kryterium, a ekran o większej gęstości
    dostaje detal, który ma czym pokazać. Poziomów są cztery: od 90 px pełna
    siatka (LOD0), 45–90 px siatka zredukowana (LOD1), 22–45 px zgrubna bryła
    ze skinningiem jednokościowym (LOD2), poniżej 22 px sama sylwetka (LOD3).
    Górne rzędy dalszej trybuny trafiają dzięki temu na dwa najtańsze poziomy,
    a bliska trybuna zostaje na pełnej geometrii.
  • Kibic, którego środek trafia w pas przy krawędzi obrazu (5% krótszego boku
    widoku), schodzi o jeden poziom niżej; przy górnej krawędzi kadru
    najdalsze rzędy schodzą więc do sylwetki. Pas wyjścia jest szerszy od pasa
    wejścia (8%), więc postać stojąca dokładnie na granicy nie przełącza
    poziomu w kółko. Kibice dwóch pierwszych rzędów przy samym boisku
    zachowują LOD0, dopóki mają co najmniej 60 px wysokości — najbliższa
    trybuna nigdy nie traci detalu.
  • Oba progi mają 15% histerezy: detal spada dopiero wyraźnie poniżej progu,
    a wraca dopiero wyraźnie powyżej, więc drobny ruch kamery nie powoduje
    przeskoków. Przeliczenie nie odbywa się co klatkę — populacja jest
    rozłożona na kolejne klatki tak, że pełne przejście po wszystkich kibicach
    zajmuje 0,25 s, a koszt na klatkę pozostaje stały niezależnie od liczby
    widzów. Po każdym pełnym przejściu wybierana jest ponownie aktywna kamera,
    dzięki czemu powtórka przejmuje sterowanie poziomami razem z obrazem.
  • Zredukowane siatki powstają raz przy budowie tłumu i są współdzielone
    przez wszystkich kibiców z tego samego prefabu; między poziomami zmienia
    się wyłącznie referencja siatki w rendererze. Redukcja zwija krawędzie:
    krótszy z dwóch połączonych wierzchołków jest przyciągany do drugiego, aż
    siatka zejdzie do budżetu trójkątów danego poziomu (45%, 18% i 7% siatki
    autorskiej). Każdy wierzchołek, który przetrwał, jest wierzchołkiem
    autorskim — z własną pozycją, własnym miejscem w atlasie i własnymi wagami
    kości; nic nie jest uśredniane, wymyślane ani przesuwane.
  • Ta własność decyduje o czystości wyniku. Przyciągnięcie wierzchołka do
    sąsiada usuwa wyłącznie trójkąty leżące między nimi, a otaczająca
    powierzchnia zostaje zszyta, więc nie otwiera się żadna szczelina i przez
    siatkę nie prześwituje tło. Dwie rzeczy są zabronione: wierzchołek leżący
    na cięciu atlasu nie rusza się nigdy, bo trzyma jedyną kopię miejsca, w
    którym tekstura zaczyna się od nowa, a wierzchołek na otwartej krawędzi
    zwija się wyłącznie wzdłuż niej, żeby kontur się nie zapadł.
  • Wszystkie poziomy powstają w jednym przebiegu — zwijanie tylko usuwa
    geometrię, więc siatka dla każdego budżetu jest migawką po drodze w dół, a
    nie trzecim przeliczeniem tego samego modelu. Kolejność zwijania jest
    ustalona (najkrótsze krawędzie, remisy rozstrzygane identyfikatorami
    punktów), więc wynik jest identyczny na każdej maszynie. Wagi kości, bind
    pose i granice bryły są przenoszone bez zmian, dzięki czemu zredukowane
    ciało napędza ten sam szkielet i ten sam klip, a culling nie zależy od
    poziomu.
  • Modele kibiców mają włączony odczyt siatki (Read/Write), bo niższe poziomy
    powstają z autorskiej siatki w czasie gry.
  • Testy sprawdzają wybór poziomu na progach, histerezę w obie strony, pas
    krawędzi, wyjątek pierwszych rzędów, widoczność rekwizytu tuż za kadrem
    oraz to, że zredukowana siatka traci geometrię, zachowuje wagi kości i
    bind pose, nie zawiera zdegenerowanych trójkątów, powstaje
    deterministycznie, składa się wyłącznie z wierzchołków autorskich i nie
    zwiększa liczby otwartych krawędzi, czyli nie rozrywa powierzchni.
    csharp-ls nie zgłasza diagnostyki w zmienionych plikach. Unity ani testów
    nie uruchamiano zgodnie z zasadami projektu, dlatego wygląd dalszych
    trybun należy potwierdzić w scenie z kamer gry.
  • Rekwizyty stawiane z importowanych modeli — karetka i drzewa — dostają ten
    sam mechanizm. Przy wyjściu poza kadr ich renderery są wyłączane, co
    odcina nie tylko rysowanie, lecz przede wszystkim koszt mapy cieni:
    karetka rzuca cień i płaci za to nawet wtedy, gdy nikt na nią nie patrzy.
    Test widoczności działa na bryle powiększonej o jej własny rozmiar, więc
    obiekt tuż za krawędzią kadru nadal rzuca cień do środka i nie znika on
    skokowo.
  • Rekwizyt maleje geometrią według tych samych progów co kibic, a że raz
    postawiony się nie porusza, jego bryła jest mierzona jednorazowo i na
    klatkę zostaje test płaszczyzn oraz jeden rzut wysokości, trzy razy na
    sekundę. Zredukowane siatki rekwizytów są trzymane we wspólnym,
    ograniczonym cache'u pod kluczem importowanej siatki, więc przebudowa
    stadionu nie klastruje tego samego pojazdu ponownie.
  • Pomiar wielkości na ekranie i wybór aktywnej kamery mają jedną definicję
    dzieloną przez tłum i rekwizyty: kamerą jest zawsze ta o najwyższym depth
    spośród włączonych, więc powtórka przejmuje sterowanie poziomami razem z
    obrazem.
  • W edytorze poziom liczy się dodatkowo względem kamery otwartego okna Scene
    i wybierany jest ten drobniejszy z dwóch. Dzięki temu przybliżenie w Scene
    view pokazuje siatkę należną temu przybliżeniu, a nie tę wybraną dla kadru
    gry, więc jakość redukcji da się ocenić zoomem. Rekwizyt wyłączony dla
    kadru gry zostaje w tym widoku narysowany, żeby podgląd stadionu nie miał
    dziur. Pas krawędzi nie obowiązuje przy takim podglądzie, a cały mechanizm
    jest ograniczony do edytora — paczka ma dokładnie jeden obraz.
  • Polecenie TacticsFootball → Benchmark Still Camera (10 s) mierzy w trybie
    gry średni czas GPU i CPU na klatkę przez dziesięć sekund przy nieruchomej
    kamerze i dopisuje rozkład kibiców po poziomach. Pojedyncza klatka nie
    nadaje się do porównań, bo tłum przelicza poziomy przez ćwierć sekundy,
    pozy są rozłożone na klatki, a kolejka GPU jest opóźniona wobec CPU.

Limit klatek zależny od platformy
---------------------------------
01.09.2026, 10:48

  • Gra ustala docelową liczbę klatek na starcie, zanim wczyta pierwszą scenę:
    60 FPS na Windows i macOS, 30 FPS na iPadzie i Apple TV. Limit wybiera
    dyrektywa kompilacji platformy, więc każda paczka niesie tylko własną
    wartość.
  • Przed ustawieniem Application.targetFrameRate wyłączane jest VSync,
    ponieważ przy włączonym VSync Unity ignoruje limit i podąża za
    odświeżaniem ekranu — na monitorze 120 Hz dawałoby to dwukrotność żądanej
    wartości.
  • Ukryty obiekt przenoszony między scenami przywraca limit po powrocie
    aplikacji z tła i po odzyskaniu fokusu, bo zawieszenie aplikacji mobilnej
    potrafi zresetować żądaną liczbę klatek do domyślnej wartości platformy.

Organiczne dojścia i gęstsze obrzeża wejść
------------------------------------------
31.08.2026, 17:57

  • Osie dojść poza stadionem zachowują wszystkie dotychczasowe punkty
    wejścia, połączenia, rampy i szerokości końcowe, ale pomiędzy nimi
    otrzymują deterministyczne, łagodne meandry oraz niewielkie organiczne
    zmiany szerokości. Dokładniejsza siatka pola odległości wygładza widoczny
    kontur z kamer izometrycznych, a istniejąca przezroczysta maska nadal
    wtapia jasną, piaskowo-kamienną nawierzchnię w prawdziwą trawę bez
    dokładania boków ani colliderów.
  • Warstwa dekoracyjna pozostaje jedną lekką siatką atlasowych stempli, lecz
    przyjmuje do 140 skupisk przy dojściach oraz 8–11 skupisk wokół każdego
    drzewa. Rozmieszczenie na trawnikach preferuje pasy przy ścieżkach,
    murkach, drzewach i narożnikach wejściowych, zachowując spokojniejsze
    środki większych połaci; szesnaście wariantów atlasu nadal nie powtarza
    identycznego motywu w sąsiednim skupisku. Teoretyczny limit całej warstwy
    wynosi 528 stempli, czyli 1056 trójkątów.
  • Ciągłe podłoże StadiumGrassPainterly.png zostało zastąpione gęstą,
    malarską łąką pokrytą od brzegu do brzegu nakładającymi się liśćmi,
    trawami oraz białymi, żółtymi, różowymi i jasnofioletowymi kwiatami.
    Domyślny materiał pobiera ją w dwóch obróconych skalach, ogranicza udział
    płaskiego koloru bazowego do 6% i zwiększa rozmiar motywów z kamer gry;
    duże atlasowe rabaty przestają więc leżeć na pustej zieleni. Wbudowany
    ImageGen przygotował źródło z referencji docelowej i bieżącego zrzutu w
    /Users/siano/.codex/generated_images/01a04780-9630-72c1-a7ed-f19557a50f0a/exec-c185c4b9-f5da-4b9f-9df7-9fb7679e5465.png,
    a finalny asset 1024 px złożono jako bezszwowy, lustrzany kafel z
    mipmapami i trybem Repeat.
  • Test ścieżek wymaga niezmienionych końców połączeń i mierzalnego bocznego
    meandru na nominalnie prostym dojściu; istniejące testy nadal pilnują
    jednej manifoldowej powierzchni, miękkiego zaniku wszystkich brzegów,
    braku wejścia dekoracji na boisko, różnorodności atlasu i budżetu do 1100
    trójkątów. csharp-ls nie zgłasza diagnostyki w zmienionych plikach. Unity
    ani testów nie uruchamiano zgodnie z zasadami projektu, dlatego końcowy
    rytm ścieżek i skupisk należy potwierdzić w scenie z kamer izometrycznych.

Komplet reprezentacyjnych strojów i haftowanych herbów
------------------------------------------------------
31.08.2026, 17:10

  Nowości:
  • Hiszpania, Francja, Maroko, Szwajcaria i Portugalia otrzymują brakujące,
    bezmarkowe powierzchnie domowych oraz wyjazdowych koszulek, a także
    odpowiadające im atlasy awaryjne. Nowe komplety korzystają z istniejących
    narodowych palet TeamKit, gładkiej plastelinowej powierzchni, krótkich
    rękawów, właściwych spodenek i wełnianych getr bez zmiany geometrii
    postaci.
  • Dwanaście reprezentacji poza Polską i Norwegią otrzymuje osobne,
    przezroczyste herby w jednym stylu gęstego haftu: uproszczone narodowe
    tarcze bez napisów, marek ani skopiowanych znaków federacji. Reprodukcyjny
    generator rozdziela jeden spójny arkusz źródłowy ImageGen na kwadratowe
    tekstury 256 px, zachowując białe nici i usuwając wyłącznie tło połączone
    z krawędzią.
  • Wszyscy zawodnicy z pola poza Norwegią korzystają z jednej wspólnej reguły
    wypalania herbu: znak jest wycentrowany na piersi, zachowuje proporcje i
    rozmiar ustalony wcześniej dla Polski oraz pozostaje wyłącznie częścią
    atlasu koszulki. Norwegia zachowuje dotychczasowy osobno pozycjonowany
    herb; bramkarze i geometria wszystkich postaci pozostają bez zmian.
  • Reprezentacja jest przekazywana jawnie do wspólnej metody dzielącej
    skinned mesh na strefy stroju. Usuwa to błąd kompilacji spowodowany
    odwołaniem z tej metody do zmiennych player i kit, które istnieją
    wyłącznie w nadrzędnym konstruktorze modelu.
  • Testy zasobów obejmują oba warianty pięciu nowych kompletów, wymagają
    centralnego herbu na wszystkich wspólnych strojach poza Norwegią oraz
    pilnują, że znaki nie powstają jako dodatkowa geometria. Skrypty Python
    przechodzą kontrolę składni, kompletność i wymiary obrazów oraz unikalność
    GUID-ów zostały sprawdzone, a csharp-ls nie zgłasza diagnostyki. Unity ani
    testów nie uruchamiano zgodnie z zasadami projektu, dlatego końcowy wygląd
    należy potwierdzić w scenie.

Właściwe proporcje i rozmiar polskiego herbu
--------------------------------------------
31.08.2026, 16:28

  Poprawki:
  • Wypalanie polskiego herbu na koszulkach domowych i wyjazdowych zachowuje
    kwadratowe proporcje tekstury źródłowej. Wysokość znaku jest wyliczana ze
    światowej szerokości projekcji i stosunku wymiarów pliku, zamiast z
    niezależnego procentu wysokości tułowia, dlatego tarcza z orłem nie jest
    pionowo rozciągnięta. Znak zajmuje 30% szerokości tułowia, czyli jest
    dwukrotnie większy w obu wymiarach od pierwszej proporcjonalnej wersji.
    Zmiana dotyczy wyłącznie rastra herbu i nie modyfikuje geometrii zawodnika
    ani pozostałych elementów stroju.
  • Test zasobu wymaga wersjonowanego atlasu polskiej koszulki z zachowanymi
    proporcjami herbu. csharp-ls nie zgłasza diagnostyki w zmienionych
    plikach; Unity ani testów nie uruchamiano zgodnie z zasadami projektu,
    dlatego rozmiar znaku należy potwierdzić z przedniej kamery stadionowej.

Proporcje i domknięte krawędzie stroju z autorskiego atlasu
-----------------------------------------------------------
31.08.2026, 15:02

  • Spodenki zawodników z pola korzystają z tej samej autorskiej siatki UV i
    tego samego maskowanego atlasu drużyny co koszulka. Właściwy kolor
    TeamKit.Shorts jest zapisany w atlasie, a biały kolor materiału pozostaje
    wyłącznie neutralnym mnożnikiem, więc mechanizm przygaszania i ponownej
    aktywacji zawodnika nie zastępuje już barwy kompletu przypadkową bielą.
  • Powłoka stroju zachowuje oryginalną topologię, UV i liczbę wierzchołków
    modelu. Spodenki kończą się wyżej nad kolanem, a getry sięgają wyżej pod
    kolano, dzięki czemu pomiędzy nimi pozostaje krótki, naturalnie położony
    pas nogi; oba progi są wyznaczane na kanonicznym modelu niezależnie od
    wzrostu zawodnika. Osobne maski są rasteryzowane wyłącznie na wyspach UV
    nóg, a czteropikselowy margines koloru, niewidoczna zakładka na granicy
    stref i łagodniejszy próg wycięcia zamykają filtrowane szwy UV oraz
    trójkątne prześwity nad getrami. Nie powstają dodatkowe bryły, cięcia ani
    interpolowane wierzchołki, a ciągła bryła skóry pozostaje widoczna
    wyłącznie w zamierzonym odstępie bez paneli, klinów i zmiany karnacji.
  • Wspólna ścieżka atlasu wszystkich zawodników z pola tworzy gładką, poziomą
    tylną krawędź koszulki pod karkiem, zgodną z referencją sylwetki. Dolne
    tylne trójkąty karku, które źródłowy rig przypisywał do pustej strefy
    skóry zewnętrznej powłoki, są kierowane do strefy koszulki na podstawie
    wspólnej obwiedni głowy i karku. Pozioma maska jest rasteryzowana na
    koszulce oraz warstwie detali głowy, dlatego skóra nie tworzy wycięcia na
    plecach, przedni dekolt i twarz pozostają niezmienione, a wszystkie
    reprezentacje korzystają z jednej reguły.
  • Ornament, pasy, herb i numer koszulki są po wypaleniu zachowywane
    wyłącznie na źródłowej wyspie koszulki. Wyspy spodenek, skóry, getrów i
    butów są przywracane z bazowego atlasu drużyny, dlatego wzór Argentyny ani
    numer nie mogą tworzyć ogona lub body na miednicy. Bramkarz i kibice nie
    przechodzą przez zmienioną ścieżkę.
  • Testy strukturalne wymagają osobnych wydłużonych atlasów spodenek i getr z
    zakładką graniczną, wspólnej gładkiej tylnej krawędzi koszulki w materiale
    ubrania oraz detali głowy, zamkniętych szwów UV, pokrycia właściwych
    części źródłowej wyspy skóry nogi, oryginalnej liczby wierzchołków oraz
    identycznych bazowych pikseli poza wyspą koszulki. csharp-ls nie zgłasza
    diagnostyki w zmienionych plikach; Unity ani testów nie uruchamiano
    zgodnie z zasadami projektu, dlatego efekt należy potwierdzić na
    kompletach domowych i wyjazdowych w scenie.

Warstwowe stroje na jednolitej bryle ciała
------------------------------------------
30.08.2026, 12:53

  Poprawki:
  • Kanoniczna, jednolita skala podczas projekcji stroju jest stosowana
    wyłącznie do zawodników z pola. Bramkarz wraca do niezmienionej ścieżki
    budowania swojego osobnego modelu i materiałów, z właściwą skalą
    wynikającą z jego wzrostu już w chwili konstrukcji.
  • Każdy zawodnik z pola ma pełną, ciągłą kopię skinned mesha podbarwioną
    jednym płaskim materiałem właściwej karnacji, bez tekstury i bez podziału
    na strefy. Koszulka, spodenki, getry oraz buty tworzą osobną, minimalnie
    odsuniętą powłokę nad ciałem; jej strefy skóry są puste, a wszystkie wyspy
    skóry odziedziczone z oryginalnego atlasu mają alpha clipping. Nawet
    trójkąt przecinający krawędź rękawa albo kołnierza pokazuje więc bazowe
    ciało zamiast kanonicznego odcienia z atlasu. Oczy, brwi i usta pozostają
    na wycinanej warstwie detali twarzy, której piksele skóry również są
    przezroczyste.
  • Dół spodenek jest wycinany bezpośrednio w skinned meshu: trójkąty
    przecinające wysokość nogawki są dzielone, a nowe wierzchołki interpolują
    pozycję, normalną, styczną, UV oraz wagi kości. Nie ma dodatkowego
    pierścienia ani obcej bryły na udzie; spodenki pozostają jedną deformowaną
    powierzchnią i kończą się równą krawędzią niezależnie od wzrostu oraz
    pozy. Bramkarz nie przechodzi przez tę ścieżkę.
  • Spodenki zawodników z pola nie próbkują już wspólnego atlasu postaci. Cała
    ich strefa używa własnego, pozbawionego tekstury materiału w kolorze
    TeamKit.Shorts, dzięki czemu interpolowane UV przy równym dole nogawek nie
    mogą trafić w wyspy karnacji; powierzchnia pozostaje jednolita i
    plastelinowa na każdym zawodniku.
  • Szaliki kibiców rozciągają tylko dwa przeguby głównego łańcucha ramienia.
    Kości skrętne i palce zachowują pozycje z bind pose, więc skóra części
    widowni nie rozrywa się już w ciemne, kolczaste bryły pomiędzy kibicami w
    narodowych barwach. Test obejmuje oba modele kibiców i pilnuje, że boczne
    gałęzie szkieletu nie są przesuwane.
  • Testy strukturalne wymagają pełnego jednopowierzchniowego mesha skóry,
    pustej strefy skóry w powłoce ubioru, przezroczystości każdego źródłowego
    piksela skóry w atlasowych materiałach odzieży, dodatniego odsunięcia
    ubioru ponad ciało, wycinanych detali twarzy, różnych pojedynczych
    karnacji na zawodnikach o różnych wzrostach, interpolowanych wierzchołków
    dołu spodenek w tej samej skinned siatce bez dokładanych mankietów oraz
    niezależnego od tekstury materiału spodenek o dokładnym kolorze kompletu.
    csharp-ls nie zgłasza diagnostyki w zmienionych plikach; Unity ani testów
    nie uruchamiano zgodnie z zasadami projektu, dlatego efekt należy
    potwierdzić w scenie na pełnym składzie.

Identyczne stroje niezależnie od wzrostu zawodnika
--------------------------------------------------
29.08.2026, 18:35

  Poprawki:
  • Wzrost zawodnika jest nakładany dopiero po wyznaczeniu stref ubioru i
    wypaleniu powierzchni na kanonicznym modelu o jednolitej skali. Zawodnicy
    od 150 do 220 cm otrzymują teraz identyczny podział koszulki, spodenek i
    rękawów oraz ten sam raster wzoru; nowy test porównuje trójkąty obu stref
    i piksele koszulki na skrajnych wysokościach.
  • Atlas odzieży nie zawiera indywidualnej karnacji zawodnika, dzięki czemu
    cała drużyna współdzieli jeden kanoniczny raster koszulki, spodenek i
    wykończeń niezależnie od wzrostu oraz odcienia skóry.
  • Usunięto sześć prowizorycznych, geometrycznych pseudoherbów oraz ich
    wypalanie i odpowiedniki w atlasach awaryjnych. Włochy, Anglia, Belgia,
    Brazylia, Holandia i Meksyk pozostają zgodnie z założeniem bez znaków
    federacji i bez logo producentów; zaakceptowane wcześniej herby Polski i
    Norwegii nie zostały zmienione.
  • Ornament wyjazdowej Argentyny został ograniczony do barków i boków. Środek
    oraz dolny pas koszulki są czyste i grafitowe, dzięki czemu strój ma
    czytelny, poziomy dół i nie przypomina wzorzystego body.
  • csharp-ls nie zgłasza diagnostyki w zmienionych plikach. Unity ani testów
    nie uruchamiano zgodnie z zasadami projektu, dlatego poprawkę należy
    potwierdzić na pełnym składzie w scenie.

Spójna trawa i dojścia dopasowane do wału
-----------------------------------------
29.08.2026, 18:26

  • Cały generowany teren trawiasty otoczenia otrzymał jedną bezszwową,
    malarską teksturę bazową próbkowaną w przestrzeni świata. Zamiast
    spokojnej, ciemnej trawy pokazuje ona ciągły dywan drobnych źdźbeł,
    koniczyny, niskich liści i maleńkich białych, żółtych oraz różowych
    kwiatów. Jej udział w albedo wzrósł do 72%, a większe atlasowe rabaty mają
    88% krycia, więc pozostają czytelne, lecz miękko wtapiają się w bogate
    podłoże. Zmiana nie dotyka murawy boiska i nie nadpisuje materiału trawy
    wskazanego ręcznie w Inspectorze.
  • Teksturę StadiumGrassPainterly.png przygotował wbudowany ImageGen jako
    kwadratową, równomiernie zarośniętą powierzchnię widzianą dokładnie z
    góry, bez ścieżek, kamieni, dużych kęp, obiektów, perspektywy i
    kierunkowych cieni. Źródło finalnej generacji zapisano w
    /Users/siano/.codex/generated_images/01a04780-9630-72c1-a7ed-f19557a50f0a/exec-5095470d-f452-4d3d-99d4-d536aa39c3a6.png,
    a asset 1024 px złożono lustrzanie w bezszwowy kafel z mipmapami i trybem
    Repeat.
  • Osobne atlasowe skupiska pozostają wewnątrz właściwego otoczenia stadionu;
    usunięto ich pas po zewnętrznej stronie kamiennego obrysu, gdzie nie są
    widoczne z kamer gry. Nowy atlas 4×4 zawiera szesnaście odmiennych,
    zwartych rabat: wysokie i niskie trawy, szerokie liście, wydłużone
    obrzeże, dwa układy kamieni oraz mieszanki białych, żółtych i różowych
    kwiatów. Większe, częściowo zachodzące na siebie stemple tworzą gęstą łąkę
    wzdłuż ścieżek, pod drzewami i na wolnych trawnikach, nadal jako jedna
    lekka siatka bez colliderów. Tylne dojścia sektorów składają się z
    płytkich stopni osadzonych tuż nad rzeczywistą powierzchnią zielonego
    wału, a ich poręcze zmieniają wysokość razem z profilem skarpy zamiast
    ciągnąć się w powietrzu ponad ukrytymi stopniami.
  • Atlas rabat przygotował wbudowany ImageGen w dwóch przebiegach: najpierw
    jako dokładną siatkę 4×4 stylizowanych, widzianych z góry kęp na
    przezroczystym tle
    (/Users/siano/.codex/generated_images/01a04780-9630-72c1-a7ed-f19557a50f0a/exec-fb8254a1-346b-4874-ad42-83b4ac7d292e.png),
    następnie z jednolitym tłem chroma do precyzyjnego odzyskania alfa
    (/Users/siano/.codex/generated_images/01a04780-9630-72c1-a7ed-f19557a50f0a/exec-9e57dea2-6196-46b5-8576-f162edaa1c35.png).
    Finalny asset ma 1024 px, oczyszczony kanał alfa i zachowane odstępy
    między komórkami. Test zasobów wymaga tekstury Repeat z mipmapami i
    poprawnego przypięcia do domyślnego materiału, gęstej, lecz ograniczonej
    liczby lekkich stempli oraz co najmniej dwunastu użytych wariantów; test
    schodów próbuje ich bieg w kilku miejscach i wymaga widocznych stopni
    ponad powierzchnią wału oraz połączenia z górnym tarasem. csharp-ls nie
    zgłasza błędów; Unity ani testów nie uruchamiano zgodnie z zasadami
    projektu, więc końcowy efekt wymaga oceny użytkownika w scenie.

Seria bezmarkowych strojów reprezentacji 2026
---------------------------------------------
29.08.2026, 18:18

  • Włochy, Anglia, Belgia, Brazylia, Holandia i Meksyk otrzymały po dwa
    komplety 2026, a Norwegia osobny komplet wyjazdowy. Projekty zachowują
    charakterystyczne narodowe palety i czytelne wzory: włoskie laury i
    krawiectwo, angielskie prążki i krzyże, belgijską geometrię, brazylijskie
    fale oraz drapieżny deseń, holenderskie promienie i kontrastowe skosy,
    norweskie runy oraz meksykańskie greki.
  • Wszystkie trzynaście wariantów współdzieli dokładnie ten sam sposób
    podziału i renderowania modelu co zaakceptowana Polska: oryginalne UV,
    równe krótkie rękawy, gładkie plastelinkowe koszulki, spodenki i
    wykończenia bez map normalnych oraz metaliczności, a także getry z grubą
    warstwą wełnianego albedo i reliefu. Numery i uproszczone, bezmarkowe
    znaki narodowe są wypalane w zakrzywioną powierzchnię koszulki zamiast
    dokładania osobnej geometrii.
  • Palety danych, właściwe powierzchnie obu wariantów i awaryjne atlasy
    zostały zsynchronizowane. W szczególności Brazylia wyjazdowa ma królewski
    błękit z czarnymi spodenkami i żółtym wykończeniem, Holandia wyjazdowa
    białą bazę z koralowo-czarnym wzorem, a Norwegia wyjazdowa pełny czarny
    komplet z grafitowym ornamentem.
  • Testy assetów obejmują każdy nowy wariant, zachowanie UV i wspólnej
    geometrii, wybór powierzchni, brak logo producentów i osobnych nakładek,
    gładkie materiały odzieży, wełniane getry oraz numer. csharp-ls nie
    zgłasza diagnostyki w zmienionych plikach; zgodnie z zasadami projektu
    Unity ani testów nie uruchamiano, więc komplety wymagają końcowej oceny
    użytkownika w grze.

Wypełnione trawniki między dojściami
------------------------------------
29.08.2026, 14:06

  • Po detalach skupionych przy krawędziach generator dodaje do 180 kolejnych
    atlasowych skupisk na całych dostępnych trawnikach wewnątrz obwodu
    stadionu. Rozmieszczenie jest deterministyczne i lekko rozluźnione
    minimalnym odstępem, dzięki czemu zielone kliny nie pozostają puste, ale
    dekoracje nie tworzą regularnej siatki.
  • Wypełnienie korzysta z rzeczywistego wewnętrznego obrysu zewnętrznego
    chodnika oraz dotychczasowych testów kolizji. Nie wchodzi na boisko,
    chodnik obwodowy, dojścia, trybuny, drzewa ani strefę techniczną i nadal
    mieści całość w jednym bezcieniowym meshu atlasowym o niewielkim koszcie.
  • Test kontraktowy wymaga teraz wyraźnie gęstszej warstwy 300–1100
    trójkątów. csharp-ls nie zgłasza błędów; Unity i testów nie uruchamiano
    zgodnie z zasadami projektu, więc gęstość wymaga oceny użytkownika w
    scenie.

Wyraźnie różniejsze skupiska przy ścieżkach
-------------------------------------------
29.08.2026, 13:53

  • Atlas detali terenu został ponownie przygotowany przez wbudowany ImageGen
    jako szesnaście czytelnie odmiennych wycinanek: cztery sylwetki trawy,
    cztery skupiska chwastów i kwiatów, cztery układy kamieni oraz cztery
    wydłużone pasy na obrzeża ścieżek. Tło techniczne usunięto bez jasnej
    obwódki, więc warianty nie wyglądają już z góry jak powtarzane blade
    okręgi.
  • Generator przechodzi przez pełną pulę atlasu w zbalansowanej kolejności i
    odrzuca identyczny kafel w sąsiednim skupisku; bardzo blisko siebie nie
    układa również dwóch wariantów tej samej rodziny. Kamienie otrzymują
    mniejszą powierzchnię, a dekoracje brzegowe wyraźnie wydłużoną sylwetkę,
    przy zachowaniu pojedynczego wspólnego mesha i materiału.
  • Test warstwy wymaga teraz użycia co najmniej dwunastu wariantów i sprawdza
    minimalny odstęp między powtórzeniami tego samego kafla. csharp-ls nie
    zgłasza błędów; zgodnie z zasadami projektu Unity ani testów nie
    uruchamiano, więc końcową kompozycję należy ocenić w scenie.

Stroje domowe i wyjazdowe Argentyny 2026
----------------------------------------
29.08.2026, 13:51

  • Domowy komplet Argentyny korzysta z oficjalnej palety 2026: ciepłej bieli,
    lodowego i jasnego błękitu oraz bardzo ciemnego granatu. Koszulka ma
    szerokie pionowe pasy z łagodnym błękitnym przejściem, granatowy kołnierz
    z lodowym brzegiem i dopasowane mankiety; uzupełniają ją granatowe
    spodenki oraz białe getry.
  • Wyjazdowa koszulka ma grafitowoczarną bazę z dużym malarskim ornamentem
    inspirowanym argentyńskim fileteado: wijące się liście i zawijasy
    przechodzą przez królewski, kobaltowy i jasny błękit z oszczędnymi białymi
    akcentami. Biały brzeg kołnierza i mankietów domyka projekt; spodenki i
    getry pozostają grafitowoczarne. Źródłowy ornament powstał przez wbudowany
    ImageGen na podstawie oficjalnej koszulki, a generator kotwiczy go w
    kontrolowanej palecie i deterministycznie wypala w assety gry.
  • Oba wzory są nakładane metodą sprawdzoną na Norwegii i Polsce:
    rasteryzowane na podstawie położenia bryły w istniejące wyspy oryginalnego
    atlasu modelu, bez modyfikowania UV. Krótkie rękawy są teraz odcinane
    osobno dla każdej strony płaszczyzną prostopadłą do osi bark–łokieć,
    dzięki czemu zachowują równy mankiet bez kulistego efektu bufki; tę samą
    poprawną geometrię współdzielą stroje Norwegii i Polski. Szwy oraz numer
    zachowują poprawne położenie, a numer jest malowany w całości również
    przez błękitne pasy oraz ornament. Koszulki, spodenki i wykończenie nie
    używają map normalnych ani metaliczności i pozostają gładkie,
    plastelinkowe; getry zachowują grubą wełnianą warstwę.
  • Zgodnie z zakresem nie dodano herbu federacji, tarczy mistrzowskiej, logo
    producenta, znaków na ramionach, napisów ani metek. Awaryjny model
    proceduralny otrzymał osobne gładkie atlasy obu kompletów zamiast starej
    fototekstury domowej; w wariancie wyjazdowym nie dokłada już domowych
    pasów jako oddzielnej geometrii.
  • Test assetów obejmuje oba warianty, zachowanie oryginalnych UV, wybór
    właściwej powierzchni, barwy wszystkich części, gładkie koszulki i
    spodenki, wełniane getry, pełny numer oraz brak osobnych znaków federacji
    i producenta. csharp-ls poprawnie wczytał rozwiązanie; Unity i testów nie
    uruchamiano, dlatego efekt wymaga oceny użytkownika w grze.

Gęstsze teksturowane obrzeża trawników
--------------------------------------
29.08.2026, 13:10

  • Rzadkie pojedyncze bryłki zastąpiono 16-polowym atlasem RGBA z malarskimi
    skupiskami trawy, chwastów, białych i żółtych kwiatów oraz drobnych
    kamieni. Atlas powstał przez wbudowany ImageGen, został oczyszczony z tła
    podglądowego i ma zachowaną przezroczystość, mipmapy oraz miękkie,
    organiczne krawędzie.
  • Liczba skupisk przy dojściach wzrosła do 78, próbki zewnętrznego obrzeża
    występują dwukrotnie częściej, a każde istniejące drzewo otrzymuje od
    trzech do pięciu nieregularnych łat. Rozmiar, wydłużenie, obrót i kafel
    atlasu są deterministycznie zróżnicowane; środki trawników nadal pozostają
    spokojniejsze, a boisko, ścieżki i istniejąca infrastruktura są omijane.
  • Cała warstwa korzysta z jednego przezroczystego materiału i jednego
    łączonego mesha. Każde skupisko to tylko poziomy quad dopasowany
    narożnikami do wysokości terenu, więc gęstszy efekt wymaga około 80–600
    trójkątów zamiast wcześniejszego budżetu 6000 i nie rzuca ani nie odbiera
    cieni.
  • Test infrastruktury sprawdza teraz pojedynczy materiał atlasowy,
    przezroczystą kolejkę renderowania, rozdzielczość 1024 px, co najmniej
    osiem użytych wariantów UV, gęstszy budżet quadów, deterministyczną
    przebudowę i brak wejścia na planszę. csharp-ls nie zgłasza błędów; Unity
    i testów nie uruchamiano, więc gęstość oraz łączenie krawędzi wymagają
    sprawdzenia przez użytkownika w scenie.

Stroje domowe i wyjazdowe Polski 2026
-------------------------------------
29.08.2026, 08:23

  • Polska korzysta z zapisanej w danych narodowej palety przeznaczonej
    również dla późniejszych flag: ciepłej bieli #F3F2ED oraz czerwieni
    #CC0F1F. Domowa koszulka 2026 łączy biały, subtelnie prążkowany tułów z
    chłodnymi błękitnoszarymi rękawami, czerwonym kołnierzem V i czerwonymi
    panelami bocznymi. Komplet wyjazdowy ma odrębną malinową bazę #C40044,
    ciemniejsze wykończenie i malarski karminowo-bordowy marmurek z cienkimi
    jasnymi żyłkami. Oba komplety mają białe spodenki i białe getry.
  • Wzorem działającego stroju Norwegii polskie wzory są rasteryzowane w
    istniejące wyspy oryginalnego atlasu modelu na podstawie położenia tułowia
    i rękawów. Nie zastępują UV cylindryczną projekcją, dzięki czemu szwy
    modelu pozostają ciągłe, kołnierz i panele nie rozciągają się na plecy, a
    numer zachowuje poprawne położenie. Materiały koszulek, spodenek oraz
    wykończenia nie używają map normalnych ani metaliczności, więc mimo
    malowanego albedo pozostają gładkie i plastelinkowe. Getry zachowują
    wspólną projekcję grubej wełny w albedo i reliefie.
  • Dostarczona, klasyczna tarcza z detalicznym białym ukoronowanym orłem
    zastępuje geometryczny znak z pierwszej wersji. To ten sam typ orła, który
    występuje na portrecie Lewandowskiego: generator zachowuje jego haft,
    koronę, skrzydła, czerwone pole i złote detale, usuwając wyłącznie białe
    tło źródła. Herb jest mniejszy, ustawiony dokładnie na osi tułowia i
    wypalany bezpośrednio w przednią powierzchnię koszulki obu kompletów; nie
    tworzy płaskiej nakładki, nie zawiera napisu federacji ani logo
    producenta. Numery nadal są wypalane w plecy.
  • Awaryjny model proceduralny otrzymał osobne atlasy domowy i wyjazdowy z
    tymi samymi wzorami koszulek, białymi dolnymi częściami oraz jedną
    wycentrowaną tarczą na wyspie przodu. Generator deterministycznie odtwarza
    oba atlasy, obie powierzchnie koszulek oraz herb z zachowanych plików
    źródłowych. Nie dodaje logo producenta, napisów federacji ani metek.
  • Test assetów obejmuje oba polskie komplety, zachowanie wszystkich
    oryginalnych współrzędnych UV tak jak w stroju Norwegii, właściwy wzór
    koszulki dla wariantu domowego i wyjazdowego, białe spodenki oraz getry,
    gładkie materiały, wełnianą warstwę getrów, herb, numer i brak osobnej
    nakładki herbu. csharp-ls poprawnie wczytał rozwiązanie; zgłosił wyłącznie
    istniejące ostrzeżenia o odwołaniach metadanych. Unity i testów nie
    uruchamiano, dlatego efekt na animowanym modelu wymaga oceny użytkownika w
    grze.

Malarskie detale trawników wokół stadionu
-----------------------------------------
29.08.2026, 08:07

  • Wokół dojść, przy zewnętrznym murku oraz miejscami pod drzewami i obok
    nich powstają deterministyczne, nieregularne skupiska drobnych dekoracji.
    Obejmują kępki trawy o zróżnicowanych źdźbłach, niskie rozetowe chwasty,
    małe białe i przygaszone żółte kwiaty oraz niewielkie fasetowane kamienie.
    Zagęszczenie skupia się na przejściach i obrzeżach; środki większych
    połaci trawy pozostają spokojniejsze.
  • Rozmieszczenie korzysta z rzeczywistej odległości od połączonej siatki
    dojść, zewnętrznego obrysu chodnika i pozycji istniejących drzew.
    Dekoracje podążają za wysokością obecnego terenu, omijają boisko, widoczną
    powierzchnię ścieżek oraz geometrię trybun i zaplecza. Nie zmieniają
    przebiegu ścieżek, murków, drzew, bramy, kamer, UI ani gameplayu.
    Przełącznik Show Ground Details na StadiumInfrastructure pozwala wyłączyć
    wyłącznie tę warstwę.
  • Wszystkie drobiazgi są prostą geometrią generowaną w Unity i trafiają do
    jednego mesha z pięcioma współdzielonymi matowymi materiałami: dwiema
    naturalnymi zieleniami, przygaszoną żółcią, kremową bielą i ciepłą
    szarością kamienia. Mesh nie ma colliderów, Rigidbody, animacji ani pracy
    co klatkę, nie rzuca cieni i ma budżet do 6000 trójkątów.
  • Istniejący test infrastruktury obejmuje teraz obecność pięciu rodzajów
    wykończenia, budżet geometrii, brak wejścia na planszę, niskie
    zróżnicowane sylwetki, deterministyczną przebudowę, wyłączanie samej
    warstwy oraz zwalnianie wygenerowanego mesha i materiałów. csharp-ls nie
    zgłasza błędów; Unity i testów nie uruchamiano, więc efekt wizualny wymaga
    sprawdzenia przez użytkownika.

Więcej haseł na bannerach bez powtórzeń
---------------------------------------
28.08.2026, 20:29

  • Każda z 14 reprezentacji ma dziesięć krótkich haseł zamiast trzech;
    rozszerzono też neutralny zestaw zastępczy do dziesięciu tekstów.
    Zachowano wcześniejsze hasła, narodowe kolory i dotychczasowe tablice 3D.
  • Wszystkie dziesięć bannerów korzysta ze wspólnej rezerwacji użytych
    napisów. Żaden napis nie powtarza się na stadionie, również za bramkami,
    przy narożnikach, w meczu dwóch identycznych reprezentacji oraz między
    zespołami mającymi wspólne hasło. Porównanie ignoruje wielkość liter;
    przebudowa zeruje rezerwacje i zachowuje deterministyczny wybór.
    Rozmieszczenie, liczba i wygląd tablic pozostają bez zmian.
  • Rozszerzono istniejący test zamocowanych bannerów o unikalność napisów
    oraz dodano sprawdzenie selektora dla wszystkich par reprezentacji,
    wariantów zastępczych i ponownej przebudowy. Diagnostyka csharp-ls nie
    zgłasza błędów; Unity i testów nie uruchamiano. Bez zmian gameplayu i
    UUID.

Malarskie kamienne ścieżki stadionowe
-------------------------------------
28.08.2026, 20:04

  • Dotychczasowe dojścia wejściowe, odgałęzienia do sektorów, krótkie
    podejścia do schodów i zatoki oraz chodnik obwodowy otrzymują dostarczoną
    teksturę jasnych piaskowych płyt i ubitej ziemi. Obraz pozostaje
    niezmieniony; import ogranicza go do 1024, używa mipmap, filtrowania
    trójliniowego i lustrzanego powtarzania. Wspólne UV w płaszczyźnie świata
    utrzymują skalę płyt między odcinkami i po zmianie skali stadionu.
  • Dojścia tworzą jedną siatkę powierzchniową wyciętą z sumy łagodnie
    zakrzywionych tras. Wspólne wierzchołki na skrzyżowaniach zastępują
    nakładające się trapezy; nie ma pionowych boków ani zamknięć wystających
    płyt. Zachowano końce tras i przybliżone szerokości, zaokrąglono węzły
    oraz zakręt od wejścia do karetki. Wysokość podąża za istniejącym terenem
    i łagodnie dochodzi do poziomu podestów sektorów; boisko i obrysy drzew są
    wyłączone z powierzchni ścieżek.
  • Szeroki, nieregularny brzeg siatki wygasa przez alpha do rzeczywistej
    trawy, bez malowanego zielonego obramowania. Współdzielony materiał siatki
    nie zapisuje głębokości ani nie rzuca cieni; nie nakłada osobnych pasów na
    siebie w węzłach. Shader rozjaśnia kamień do spokojnego piaskowego
    odcienia i zmniejsza kontrast. Chodnik obwodowy pozostaje
    nieprzezroczysty, bo wypełnia otwór w terenie; zmienia się jego
    wykończenie, nie geometria terenu ani murku.
  • Kamienne wykończenie ma osobny współdzielony materiał infrastruktury.
    Betonowe bramy, stopnie, podesty schodów i stanowisko karetki oraz
    metalowe poręcze zachowują wcześniejsze materiały i geometrię. Boisko,
    trybuny, kibice, bannery, oba murki, drzewa, karetka, panorama i UI
    pozostają poza zakresem zmian. Zachowano możliwość podania własnego
    materiału chodnika w Inspectorze i zwalnianie wygenerowanych zasobów.
  • Rozszerzono istniejące testy o połączone dojścia i krzywiznę podejścia do
    karetki w dwóch skalach, brak pionowych ścian i przerw w siatce,
    wygaszenie na każdej granicy, poziom płaskiej trasy nad gruntem, ciągłość
    UV i skalę płyt, osobne materiały techniczne, odstępy od drzew, niezależne
    zwalnianie siatki ścieżek oraz własny materiał chodnika. Siatka dojść ma
    osobny budżet 6000 trójkątów, a dotychczasowy limit infrastruktury
    pozostaje bez zmian. Diagnostyka csharp-ls nie zgłasza błędów; Unity,
    kompilacji shaderów i testów nie uruchamiano. Efekt wizualny wymaga
    sprawdzenia w grze przez użytkownika.

Kamienne obrzeża i bannery zamocowane na murku boiska
-----------------------------------------------------
28.08.2026, 17:51

  • Zewnętrzna krawędź istniejącego chodnika otrzymuje niski kamienny murek
    oporowy, zachowany zgodnie z późniejszym poleceniem użytkownika. Równa
    góra pozostaje na poziomie dojść, a trawa po zewnętrznej stronie schodzi
    do podstawy i łagodnie wraca do istniejącego terenu. Panorama i daleki
    teren nie są zmieniane. Wall Height (domyślnie 0,6 pola) i Wall Tiling są
    dostępne na StadiumGroundEnvironment; odświeżanie przez Rebuild Ground.
  • Osobny wewnętrzny murek zastępuje cztery porcelanowe elementy obrzeża
    zielonego pasa przy murawie. Zamknięty obwód wynika wyłącznie z
    PitchApronBounds: proste boki, po sześć odcinków łuku w każdym narożniku,
    fazowana równa góra. Nie zmienia boiska, linii, bramek, flag ani
    szerokości zielonego pasa poza stykiem obrzeża. Ma 336 trójkątów, jeden
    renderer i jeden materiał.
  • Wewnętrzny murek pokazuje jedną warstwę dużych jasnych bloków z
    dostarczonego pliku stone_wall_texture.png. Domyślnie wystaje 0,72 pola
    nad pas murawy; bannery zachowują wysokość 0,78 pola, dolną krawędź 0,012
    pola nad trawą i wystają 0,072 pola ponad kamień. Wysokość mocowania
    wynika z poziomu trawy, więc regulacja wysokości murku (0,45–1,2 pola) nie
    przesuwa ani nie zagłębia bannerów. Pitch Wall Height i Pitch Wall Tiling
    są na TabletopEnvironment; Rebuild Pitch Wall przebudowuje wyłącznie ten
    murek i przestawia mocowania istniejących bannerów.
  • Sześć bannerów wzdłuż trybun zachowuje napisy, barwy, proporcje, rozmiary
    i rozmieszczenie. Na krótkich bokach murku dochodzą po dwa bannery za
    każdą bramką, po jednym dla każdej drużyny: łącznie dziesięć tablic. Nowe
    pary leżą po bokach siatek, z odstępem od słupków i zaokrąglonych
    narożników; szerokość i pozycje wynikają z obrysu pasa murawy. Wszystkie
    tablice są skierowane do środka boiska, a ich tyły wpuszczone w kamień na
    0,07 pola (7 cm przy standardowej skali), pozostawiając około 0,039 pola
    wystającego frontu. Powyżej murku widoczny jest pełny, gładki tył tablicy;
    napisy są wyświetlane wyłącznie od strony murawy. Odświeżenie mocowań
    obsługuje wszystkie cztery boki bez duplikowania tablic i nie regeneruje
    tłumu ani terenu.
  • Bannery mają formę miękkich tablic 3D: grubość 14% wysokości (około 0,11
    jednostki przy standardowej skali), zaokrąglone narożniki i wygładzony
    profil przednich krawędzi. Jeden matowy materiał Lit oraz cień na kamieniu
    zastępują płaskie panele i kontrastowe paski; każda tablica ma 82
    wierzchołki i 160 trójkątów oraz zamkniętą bryłę z pełną tylną ścianą.
    Front pozostaje przed kamieniem mimo wpuszczenia tyłu w murek; rozmiar
    obrysu nie zmienia się. Napisy wykorzystują pięć blisko rozstawionych
    warstw atlasu fontu z cieniowaniem krawędzi oraz subtelny cień kontaktowy
    w jednej siatce UI — płytki relief zachowuje oryginalne hasła, diakrytykę
    i automatyczne dopasowanie tekstu, bez osobnych obiektów liter ani nowych
    tekstur. Siatki i materiały tablic są zwalniane także przy usunięciu
    komponentu.
  • Oba murki korzystają z prostych matowych materiałów: dostarczone tekstury
    kolorów ocieplone wspólnym piaskowym tintem (1, 0,95, 0,84), bez normal
    map i metaliczności. Kamień jest lekko złocistym beżem zamiast chłodnej
    szarości; oświetlenie sceny i barwy drużynowe bannerów pozostają bez
    zmian. Zewnętrzna góra używa jasnych płyt, wewnętrzne obrzeże jednej
    tekstury bloków. Powtórzenia wzdłuż boków zamykają się na całej liczbie
    kafli, UV góry są osobne, a normalne wygładzone na fazach i szwie. Import
    ma mipmapy i limit 1024. Generowane siatki i materiały są zwalniane,
    współdzielone tekstury pozostają nienaruszone. Brak colliderów, nowych
    animacji, zmian gameplayu i UUID.
  • Rozszerzono istniejące testy otoczenia o zamknięcie obwodów, równą górę,
    orientację powierzchni, wysokość i tiling, obrys zielonego pasa, mocowanie
    i zwrot dziesięciu bannerów na czterech bokach, wpuszczenie tyłów w kamień
    i odsłonięty front, zamknięcie siatek oraz orientację tylnych ścian,
    odstępy nowych par od bramek i narożników, zachowanie ich rozmiarów i
    pozycji nad trawą przy regulacji murku, niewielkie wystawanie ponad
    domyślną górę kamienia, głębokość i miękkie normalne tablic, położenie
    napisów nad frontem, warstwy reliefu z zachowaniem UV i barwy fontu,
    niezależną przebudowę oraz zwalnianie zasobów. Analiza csharp-ls
    zmienionych plików nie zgłasza błędów. Sprawdzono również statycznie
    przekrój i kopię dostarczonej tekstury; Unity ani testów C# nie
    uruchamiano.

Dojścia, zaplecze i grupy drzew przy stadionie
----------------------------------------------
28.08.2026, 14:04

  • Puste przestrzenie na obu końcach stadionu otrzymują zwężające się
    betonowe przedpola z otwartymi, zadaszonymi wejściami. Cztery krótkie
    pochyłe dojścia łączą je z pomierzonymi końcami frontowych podestów
    skrajnych sektorów. Wejścia łączą się z istniejącym obwodowym chodnikiem;
    nie mają ślepych ścian ani imitowanych otworów w litych trybunach.
  • Z tyłu każdej trybuny schody z obustronnymi poręczami prowadzą z poziomu
    chodnika po ziemnym wale do tylnej krawędzi najwyższego tarasu. Mają
    dopasowane podesty, stopnie i różne położenie wzdłuż obu trybun.
    Istniejące modele trybun, kibice, boisko, bandy, bramki i panorama
    pozostają bez zmian.
  • Przy wschodnim wejściu, poza obrysem trybun i osią bramki, znajduje się
    niewielka betonowa zatoka techniczna połączona z dojściem. Jedna karetka
    korzysta z dostarczonego przez użytkownika modelu i jego oryginalnej
    tekstury bazowej. Domyślny mnożnik skali 2 zachowuje proporcje i daje
    około 2,18 szerokości × 2,45 wysokości × 4,2 długości w jednostkach Unity
    przy rozmiarze pola 1. Zatoka dopasowuje rozmiar na zewnątrz, utrzymuje
    koła na podłożu i odstęp od poręczy, bez przesuwania bliższych krawędzi w
    stronę wejścia lub drzew. Nie ma migających świateł ani animacji.
  • Geometria infrastruktury powstaje w Unity: proste pochylnie, bryły ze
    ściętymi narożnikami i ośmioboczne poręcze. Pięć części współdzieli dwa
    proste matowe materiały; każda używa tylko potrzebnych submeshy. Pojazd i
    drzewa współdzielą importowane siatki oraz trzy matowe materiały z
    bazowymi teksturami, bez normal map i map metaliczności, z mipmapami i
    limitem importu tekstur 1024. Infrastruktura nie ma colliderów, Rigidbody
    ani aktualizacji co klatkę, nie zmienia gameplayu i nie wymaga zmiany
    UUID.
  • Dwa dostarczone warianty drzew tworzą osiem niewielkich drzew w czterech
    nieregularnych parach, w widocznych z boiska prześwitach na obu końcach
    stadionu. Rosną po bokach przedpól wejściowych, nie za długimi trybunami;
    środek wejść, dojścia i zatoka karetki pozostają wolne. Rozmiary i kąty są
    zróżnicowane, układ deterministyczny, a korzenie dopasowane do wysokości
    terenu. Całe obrysy koron z marginesem są sprawdzane względem rzutu
    rzeczywistych trójkątów trybun i infrastruktury, zamiast ich obwiedni
    obejmujących także puste kliny. Kolizja pomija drzewo zamiast zasłaniać
    dojście.
  • Modele źródłowe uproszczono w Blenderze: karetka z około 981 tys. do 6000
    trójkątów, oba drzewa z około 1,5–1,9 mln do 3500 trójkątów każde.
    Zachowano UV i bazowe kolory, obejrzano rendery uproszczonych modeli, a
    oryginalne pliki w Downloads pozostają bez zmian. Skrypt przygotowania i
    zapis pochodzenia z sumami SHA-256 są w repozytorium; nie dołączono
    niewykorzystanych ciężkich FBX-ów.
  • Komponent StadiumInfrastructure na TabletopEnvironment udostępnia
    szerokość dojść, wysokość barierek, przełącznik pojedynczej karetki i jej
    mnożnik skali (1–3, domyślnie 2) oraz wysokość i przełącznik grup drzew.
    Menu Rebuild Infrastructure odświeża samą infrastrukturę; przebudowa
    podłoża również ją dopasowuje. Siatki są zwalniane przy przebudowie, a
    współdzielone materiały przy usunięciu komponentu. Wysokość zatoki i
    podejść wynika z geometrii podłoża, bez raycastów fizyki.
  • Rozszerzone testy otoczenia obejmują dwie skale i przesunięty stadion,
    połączenia z podestami oraz górnymi tarasami, drożne wejścia,
    pozostawienie boiska i trybun bez zmian, zatokę poza trybunami, limit 6000
    trójkątów infrastruktury, budżety importowanych modeli, wysokość i długość
    karetki oraz odstęp od poręczy powiększonej zatoki, powtarzalność i
    odstępy drzew, umieszczenie koron w prześwitach na obu końcach stadionu
    oraz próbkowanie ich obrysów względem powierzchni trybun i dojść,
    przebudowę, wyłączanie dekoracji oraz zwalnianie własnych zasobów bez
    niszczenia importowanych assetów. Analiza csharp-ls zmienionego C# nie
    zgłasza problemów; Unity i testów nie uruchamiano, więc ocena obrazu
    pozostaje do weryfikacji w grze.

Chwyt szalików, kolizje kibiców i spójne tło stadionu
-----------------------------------------------------
28.08.2026, 12:03

  • Testy obejmują podparcie wszystkich odcinków źródłowego stadionu, kolizję
    z drugim osobnym modelem trybuny, odrzucanie zbyt małych miejsc,
    sprzątanie colliderów, pomiar obu sylwetek niezależny od obwiedni cullingu
    oraz proste łokcie i chwyt po kanonicznych reakcjach oraz obrotach tułowia
    0°, 75° i 180°. Dodatkowo sprawdzane jest stałe przesunięcie materiału
    szalika względem dłoni ku boisku podczas tych reakcji. Testy tła obejmują
    brak odcięcia wierzchołków panoramy przy obrocie i przybliżeniach kamery
    oraz dopasowanie zasięgu do powiększonej warstwy wzgórz bez zmniejszania
    większej wartości ustawionej wcześniej. Sprawdzają również wspólne granice
    geometrii i UV kolejnego obrazu oraz wszystkie narożniki chmur ponad
    panoramą dla kamer izometrycznej i stadionowej. Dokumentacja animacji i
    UUID klienta są zaktualizowane. Testy Unity wymagają uruchomienia przez
    użytkownika lub jego zgody; analiza statyczna nie zastępuje oceny obrazu.

  Poprawki:
  • Ręce trzymające szalik są prostowane od barku przez łokieć ku chwytowi.
    Korekta odtwarza pozycję z macierzy wiązania siatki (bindposes), również
    dla gałęzi deformujących i palców; dłoń zachowuje relację do
    przedramienia, bez niezależnego obracania nadgarstka. Oś szalika wynika z
    aktualnej linii barków, więc ręce nie zamieniają końców po obrocie tułowia
    względem kotwicy. Ramiona wykonują najkrótszy obrót od odtworzonej pozy
    bez wymuszania wspólnej normalnej dłoni w świecie na lustrzanych kościach.
    Szalik ma minimum 60% wzrostu między chwytami, żeby ręce omijały dużą
    głowę. Materiał szalika jest dodatkowo wysunięty poziomo o 3,5% wzrostu w
    stronę stałego środka boiska względem niezmienionych celów chwytu, więc
    dłonie nie podążają za przesunięciem i nie zasłaniają pasów. Kolory, pasy,
    frędzle, losowanie i częstotliwość animacji pozostają bez zmian.
  • Propozycje miejsc na odsłoniętych fragmentach stopni są weryfikowane na
    pełnej geometrii obu trybun jednocześnie, więc bryła innego modelu również
    jest przeszkodą. Tymczasowy MeshCollider, raycasty pod podeszwami i
    kapsuła z ComputePenetration sprawdzają podparcie oraz miejsce na
    sylwetkę. Brak bezpiecznego miejsca pomija postać z komunikatem błędu
    zamiast osadzać ją w betonie. Collidery służą tylko przebudowie, są
    natychmiast wyłączane i usuwane; kibice nie mają Rigidbody ani ciągłej
    symulacji fizyki.
  • Skala modelu, podeszwa i wysokość szalika wynikają z rzeczywistej siatki
    uzyskanej przez BakeMesh, nie z obwiedni renderera dla całej animacji.
    Pomiar jest współdzielony między postaciami tej samej sylwetki, więc
    wystarcza po jednym bake'u na model przy przebudowie. Pierwsza poza jest
    ewaluowana również przed widocznością w kamerze, a późniejsze próbki
    utrzymują pionowe i poziome podparcie stóp bez przesuwania postaci według
    granic cullingu.
  • Panorama używa segmentów stykających się bez nakładania przezroczystej
    geometrii. Shader miesza premultiplikowane próbki bieżącej i następnej
    ilustracji tylko raz, a powtórzenia odbijają obraz zamiast skakać między
    jego niedopasowanymi końcami. UV są ciągłe na styku segmentów, w tym
    ostatniego z pierwszym; ręcznie puste odcinki zachowują wygaszenie.
    Materiał przypada na segment, liczba rendererów i submeshy pozostaje bez
    zmian.
  • Kamera meczu i powtórek używa dalekiego odcięcia 1000 zamiast 300
    jednostek, które przecinało pierścień wzgórz o promieniu co najmniej 320 i
    odsłaniało niebo jako wielokątny ubytek zależny od kierunku patrzenia.
    Aktualizacja nieba dopasowuje zasięg aktywnej kamery do całej obwiedni
    wygenerowanego tła z marginesem 20 jednostek, również dla większych
    promieni w Inspectorze. FOV, bliskie odcięcie i ruch kamery pozostają bez
    zmian; ta korekta renderowania nie zmienia animacji ani UUID.
  • Całe billboardy chmur, włącznie z dolnymi narożnikami, są utrzymywane
    ponad górną krawędzią panoramy z konfigurowalnym marginesem domyślnie 5
    jednostek. Podniesienie w płaszczyźnie kamery zachowuje pozorny rozmiar i
    dryf; kolejka 2990 umieszcza chmury za warstwami krajobrazu. Nie zależą
    już wyłącznie od wysokości środka w kadrze, która przy kamerze patrzącej w
    dół lokowała geometrię pod terenem.

Łagodne połączenie panoramy z terenem
-------------------------------------
28.08.2026, 11:43

  • Panorama jest dopasowana do rzeczywistego zasięgu zewnętrznego terenu.
    Wszystkie jej warstwy w razie potrzeby odsuwają się wspólnie poza ten
    obrys, z zachowaniem odstępów i uwzględnieniem prostych odcinków siatki
    między próbkami łuku. Domyślny odstęp wynosi 20 jednostek świata. Boisko,
    trybuny, bandy, bramki, kamery i gameplay pozostają bez zmian.
  • Pięć dodatkowych rzędów istniejącego mesha trawy tworzy łagodne, niskie
    przedłużenie podłoża pod warstwami panoramy i 40 jednostek za najdalszą z
    nich. Przejście zaczyna się dokładnie na dotychczasowym brzegu, nie
    przesuwa istniejących wierzchołków i pozostaje poniżej stadionu; nie
    powstają nowe dekoracje, collidery ani obiekty renderujące. Przebudowa
    terenu odświeża również jego połączenie z panoramą, bez kumulowania
    kolejnych pasów.
  • Domyślny materiał trawy korzysta z prostego, matowego shadera: przy
    stadionie przyjmuje oświetlenie, cienie i SSAO, a w oddali płynnie
    przechodzi we wspólny, stonowany kolor podstawy panoramy niezależny od
    światła. Parametry przekazywane przez MaterialPropertyBlock nie modyfikują
    materiału użytkownika; własny materiał z innym shaderem pozostaje
    niezmieniony, a automatyczne przejście wymaga shadera
    TacticsFootball/StadiumGround.
  • Dolne 4 jednostki wysokości panoramy mają płynne wygaszenie
    przezroczystości, a kolor obrazu miesza się z kolorem dalekiego podłoża na
    wysokości 10 jednostek. Wygaszenie używa wysokości geometrii niezależnej
    od tilingu i odbicia tekstury, jest nakładane po odcięciu przezroczystej
    sylwetki i odsłania podłoże rozciągnięte za panoramą. Domyślne wysokości
    wzgórz, miasteczka, drzew i przemysłowej sylwetki wynoszą odpowiednio 44,
    24, 16 i 12 jednostek, żeby tło zachowało spokojną skalę. Obrazy, układ
    segmentów, seed i kolejność warstw pozostają bez zmian.
  • Inspector panoramy udostępnia odstęp od otoczenia, zagłębienie podstawy,
    wysokość wygaszenia, zakres przejścia koloru i wspólną barwę horyzontu.
    Testy istniejącej panoramy obejmują położenie styku w kamerze
    izometrycznej i trzech niskich przybliżeniach przy ośmiu kierunkach
    patrzenia, połączenie geometrii, wspólną barwę, stabilność przebudowy oraz
    odsuwanie warstw przy większym terenie. Zmiana jest wyłącznie graficzna,
    bez zmiany UUID.

  Poprawki:
  • Usunięto historyczne obniżenie panoramy o 56 pól pod dolną krawędź
    nieistniejącego już stołu. Jej centrum odpowiada poziomowi stadionowego
    gruntu, a podstawa warstw jest zagłębiona domyślnie o 1,5 jednostki w
    dalekim pasie przejściowym zamiast wisieć głęboko pod sceną.

Stadion osadzony w organicznym terenie
--------------------------------------
28.08.2026, 11:30

  • Wokół stadionu powstaje dekoracyjne podłoże z wąskim, jasnym i matowym
    chodnikiem o delikatnie zmiennej szerokości oraz szeroką trawą o
    niezależnym, asymetrycznym obrysie. Chodnik zaczyna się przy zewnętrznym
    obrysie fizycznych trybun i obudowy boiska; wolne miejsca wewnątrz tego
    obrysu wypełnia trawa zamiast betonowego placu, a środkowy otwór
    pozostawia boisko i jego obudowę odsłonięte.
  • Trawa ma zmienną szerokość, miękkie nieregularne wybrzuszenia i bardzo
    subtelne nierówności wynikające z pola szumu w płaszczyźnie terenu,
    zamiast koncentrycznych grzbietów. Dalsza część tego samego mesha łagodnie
    opada daleko poza najbliższe otoczenie stadionu; początek skarpy i jej
    zasięg zmieniają się na obwodzie, bez poziomego końcowego rantu ani
    pionowej ścianki. Zróżnicowane rozmieszczenie rzędów wierzchołków i
    naprzemienne przekątne trójkątów ograniczają regularny układ siatki.
  • StadiumGroundEnvironment na obiekcie TabletopEnvironment udostępnia w
    Inspectorze nominalną szerokość chodnika (domyślnie 0,55 pola), szerokość
    pobliskiej trawy (5 pól), amplitudę nierówności (0,16 pola, maksymalnie
    0,3) oraz materiały obu powierzchni. Puste pola materiałów tworzą proste,
    matowe materiały bez tekstur. Polecenie Rebuild Ground w menu komponentu
    odświeża samo podłoże po zmianie ustawień, bez przebudowy stadionu, tłumu
    i panoramy.
  • Drewniany stół nie jest już tworzony; wcześniej wygenerowany obiekt jest
    usuwany, a nie tylko przykrywany. Usunięto jego nieużywaną teksturę i
    materiał. Poziom podłoża nadal wynika z podstawy stadionu, a dotychczasowy
    punkt zakotwiczenia panoramy jest zachowany algebraicznie, z migracją nazw
    serializowanych ustawień. Boisko, trybuny, bandy, bramki, kamery i pozycja
    panoramy nie zmieniają się.
  • Dwa statyczne meshe mają dopasowane granice, wygładzone normalne i niski
    polycount; bazowe 96 próbek obwodu uzupełniają dokładne narożniki. Trawa
    ma przerwę pod chodnikiem, bez nakładających się współpłaszczyznowych
    powierzchni. Siatki są używane ponownie przy przebudowie, a własne
    materiały i geometria są zwalniane przy usuwaniu komponentu; materiały
    wskazane w Inspectorze nie są modyfikowane ani niszczone. Teren nie ma
    colliderów, aktualizacji w każdej klatce ani dodatkowych dekoracji i nie
    wymaga nowych zewnętrznych assetów. Zmiana jest wyłącznie graficzna, bez
    podbijania UUID.
  • Testy istniejącego otoczenia obejmują usuwanie starego stołu, zachowanie
    stadionu i położenia panoramy, zmienność szerokości i wysokości, ciągłość
    terenu przy domyślnych i minimalnych ustawieniach, otwór nad boiskiem,
    zgodność granic, kierunek trójkątów, ograniczenie wysokości oraz ponowne
    użycie i zwalnianie zasobów z zachowaniem materiałów użytkownika.

Nadrzędne zasady stylu wizualnego
---------------------------------
28.08.2026, 11:07

  • Instrukcje projektu definiują nadrzędny kierunek artystyczny nowych
    elementów świata, modeli, materiałów i dekoracji: stylizowane 3D
    przypominające ręcznie wykonaną makietę, miękkie uproszczone formy, matowe
    lub półmatowe materiały, organiczne otoczenie oraz spokojne oświetlenie
    dzienne. Spójność z postaciami i stadionem ma pierwszeństwo przed
    szczegółowością i realizmem, a ocenę assetów należy prowadzić z typowych
    kamer gry: izometrycznej, wysokiej i niskiej stadionowej.

Dwukolorowe szaliki kibiców
---------------------------
28.08.2026, 10:44

  • Losowa część kibiców gospodarzy i gości trzyma nad głową szaliki;
    neutralni pozostają bez nich. Pole StadiumCrowd._scarfProbability jest
    dostępne w Inspectorze w zakresie 0–1, domyślnie 0,28, i działa przy
    przebudowie tłumu. Osobne deterministyczne losowanie nie zmienia
    dotychczasowego rozmieszczenia, sylwetek ani reakcji. Oba kolory pochodzą
    z Shirt i Trim aktualnego KitsForMatch; szaliki odświeżają się razem z
    koszulkami, również dla kompletu wyjazdowego i meczu jednakowych
    reprezentacji.
  • Proceduralna, cienka siatka zawiera 12 naprzemiennych poprzecznych pasów i
    po cztery krótkie frędzle na obu końcach: 196 trójkątów, jeden submesh i
    jedna geometria współdzielona przez cały tłum. Dwa materiały meczu
    korzystają z dwupikselowych palet i mają włączoną możliwość GPU
    instancingu. Nie ma zewnętrznych modeli ani assetów dla reprezentacji,
    cieni, fizyki, falowania i osobnych aktualizacji akcesoriów. Siatka,
    materiały oraz palety są zwalniane razem z generowanym tłumem.
  • Szalik skaluje się do sylwetki, pozostaje ponad górną granicą głowy i ma
    stały losowy przechył ±4° oraz niewielką różnicę wysokości. Korekta obu
    ramion po próbkowaniu klipu i plantowaniu stóp ustawia dłonie na szaliku;
    krótkie ręce obecnych modeli otrzymują wymagane wydłużenie segmentów i
    kości skrętu bez powiększania dłoni. Dotyczy to obu sylwetek, kroków 12/6
    Hz oraz natychmiastowych reakcji meczowych. U posiadaczy szalików gesty
    rąk z klipów zastępuje chwyt, a reszta ciała zachowuje animację. Obwiednia
    renderowania obejmuje uniesione ręce, a widoczny szalik podtrzymuje
    próbkowanie właściciela. Zmiana pozy jest opisana w dokumentacji animacji
    i podbija UUID klienta.
  • Istniejący zestaw testów kibiców obejmuje geometrię i naprzemienność
    pasów, zakres prawdopodobieństwa, dwie różne barwy wszystkich zestawień
    drużyn, wymianę i zwalnianie wspólnych zasobów oraz chwyt i prześwit nad
    głową obu modeli po próbkowaniu wszystkich kanonicznych klipów.

Zróżnicowany i responsywny tłum na całych trybunach
---------------------------------------------------
26.08.2026, 16:47

  • Na desktopie obie trybuny mieszczą dokładnie 666 widzów: 250 gospodarzy,
    250 gości i 166 neutralnych. Każda strona dostaje 333 osoby równomiernie
    rozłożone pomiędzy 42 odcinki: 18 głównych ławek oraz po sześć lewego
    ramienia, lewego łuku, prawego łuku i prawego ramienia. Narożny odcinek
    jest wyznaczany wyłącznie z najwyższych, prawie poziomych trójkątów siatki
    danego stopnia; pionowy front i spód betonowej bryły nie przesuwają już
    środka miejsca w głąb konstrukcji. Oś główna tej powierzchni nadaje
    kierunek szeregowi, dlatego postacie podążają za kształtem trybuny zamiast
    zbijać się w środkowy prostokąt albo wychodzić poza stopień. Przypisania
    są tasowane w blokach po 3–5 osób przy zachowaniu 125/125/83 na trybunę.
    Powierzchnia podeszwy jest kotwiczona dokładnie na górze ławki lub
    narożnego stopnia bez zagłębienia w beton; deterministyczna różnica skali
    daje postaciom zróżnicowany wzrost.
  • Tłum korzysta z nowego animowanego skinned mesha, pełnego szkieletu,
    oryginalnego albedo i mapy normalnych. Spośród 50 stosów powielonych przez
    eksporter runtime wybiera po jednej kanonicznej wersji idle, wait,
    look_around, cheer, clap, trzech angry i dwóch complain. Na desktopie
    widoczne postacie mieszają klipy z wyłączonym root motion i aktualizują
    pozę oraz wzrok w rozłożonym fazowo tempie 12 Hz. iPad oraz tvOS tworzą
    dokładnie połowę tłumu — 333 osoby — i próbkują spokojny ruch z
    częstotliwością 6 Hz; iPhone zachowuje pełny profil. Kontrola widoczności
    również odbywa się dopiero przy rozłożonym fazowo kroku postaci, więc
    setki niewidocznych komponentów nie iterują po rendererach w każdej
    klatce. Po każdej ewaluacji najniższa z humanoidalnych kości stóp jest
    porównywana z zapamiętanym odstępem podeszwy od powierzchni, po czym dolna
    granica faktycznie renderowanej sylwetki dostaje dodatkową twardą korektę
    do wysokości ławki lub litego stopnia. Przesunięcie korzenia, retargeting
    ani poza nie mogą dzięki temu pozostawić żadnej części postaci w betonie.
    Poza kadrem renderer jest odrzucany przez frustum, skinned mesh nie
    aktualizuje się, Animator używa CullCompletely, a ręcznie taktowany graf
    Playables nie jest ewaluowany. Skinning ograniczono do dwóch wpływów
    kości, wyłączono rzucanie i odbieranie cieni, zaś albedo oraz normal mają
    maksymalnie 512 px. Kotwica używa zgodnej z modelem osi przodu +Z, więc
    twarz śledzi piłkę.
  • Gospodarze i goście noszą koszulki w kolorze faktycznie wybranego dla ich
    reprezentacji kompletu, łącznie z wariantem wyjazdowym rozstrzygającym
    konflikt barw. Spośród neutralnych 148 z 166 widzów na desktopie lub 73 z
    83 w profilu iPad/tvOS dostaje jedną z ośmiu barw wybieranych metodą
    najdalszego punktu spośród 24 kandydatów tak, by różniły się od obu
    koszulek meczowych oraz od siebie nawzajem; pozostali zachowują oryginalny
    atlas jako rzadszy dziewiąty wariant. Warianty są rozłożone równomiernie i
    deterministycznie. Maska atlasu obejmuje wyłącznie nasyconą czerwień
    oryginalnej koszulki, więc skóra, włosy, spodenki, skarpety oraz buty
    zachowują dostarczone kolory.
  • Tłum korzysta z dwóch osobnych humanoidalnych sylwetek. Model dziewczyny,
    jego albedo oraz normal leżą obok modelu chłopca w
    Resources/Characters/CrowdSpectator; nie importuje własnych klipów, lecz
    przez własny Avatar retargetuje dokładnie ten sam kanoniczny zestaw idle,
    wait, look_around, cheer, clap, angry i complain. Osobno tasowany
    deterministyczny roster płci nie narusza przypisania drużynowego. Ponieważ
    44% z 666 nie jest liczbą całkowitą, pełny tłum używa najbliższego
    możliwego wyniku 293 dziewczyn (43,994%): 147 na dalszej i 146 na bliższej
    trybunie. Profil 333-osobowy używa 147 dziewczyn (44,144%): odpowiednio 74
    i 73. Obie sylwetki zachowują wspólne stroje kibicowskie, reakcje,
    culling, jakość tekstur 512 px i plantowanie stóp.
  • Grupy zachowują niewidoczne przypisanie do gospodarzy, gości albo widzów
    neutralnych we wszystkich reakcjach gracza i komputera. Celne podanie oraz
    wygrany odbiór dają clap kibicom właściwej drużyny i neutralnym; strata
    piłki, niecelne podanie lub strzał i przegrany pojedynek losują u swoich
    angry/complain, podczas gdy rywale reagują cheer. Po golu swoich występuje
    mieszanka cheer/clap, po golu rywala angry/complain, a neutralni klaszczą
    do końca powtórki. Widoczna postać rozpoczyna 28% krótkiego przejścia i
    ewaluuje nowy klip bezpośrednio w obsłudze zdarzenia, więc reakcja jest
    widoczna od następnej renderowanej klatki zamiast czekać do 83 lub 167 ms
    na okresowy krok 12/6 Hz; dalszy ruch nadal korzysta z profilu
    wydajnościowego platformy, a niewidoczny tłum nie jest ewaluowany. Dobór
    wariantu wynika ze stanu meczu i pozostaje deterministyczny dla
    multiplayera oraz odtwarzania. Identyfikator zgodności klienta został
    podbity wraz z nową animacją prezentacyjną.
  • Wszystkie runtime'owe zasoby kibica są skupione w
    Resources/Characters/CrowdSpectator, obok pozostałych gotowych postaci.
    Usunięto dawną kopię z Resources/Models; ten katalog pozostaje
    przeznaczony dla bezpośrednio ładowanych modeli elementów stadionu, a
    Art/Models dla źródeł wypalanych do prefabów.

Nowy zawodnik z pola i kontekstowe animacje
-------------------------------------------
19.08.2026, 11:48

  • Zawodnicy z pola korzystają z nowego teksturowanego modelu Humanoid. Jedna
    przekolorowana kopia jego oryginalnego atlasu pokrywa całe ciało, więc
    namalowane w teksturze granice koszulki, pełnej długości spodenek i getrów
    nie są ponownie przecinane według kości; usuwa to również pasy obcego
    koloru skóry. Cała głowa używa osobnego wariantu tego samego atlasu, który
    zachowuje łysą skórę oraz zawsze białe białka oczu. Anglia otrzymuje biały
    trykot, granatowe spodenki i białe getry. Norwegia zachowuje
    czerwono-biało-czerwony komplet, a jej biało-granatowy krzyż jest
    rasteryzowany wyłącznie na czerwonych pikselach przednich wysp UV tułowia;
    twarda maska koloru stroju chroni szyję, ręce i spodenki niezależnie od
    niedokładnego podziału siatki według kości. Tą samą maską ograniczone są
    numery na plecach. Model zachowuje własne UV i normal, a getry nakładają
    dodatkowo neutralną warstwę albedo i normal grubej wełny. Materiał
    zawodnika z pola ma całkowicie wyłączone metallic, smoothness, odbicia
    środowiska, refleksy specularne i emisję, postać korzysta wyłącznie z oczu
    zawartych w nowym modelu, a czytelny, nieodwrócony numer jest
    rasteryzowany bezpośrednio w obszarze pleców indywidualnej kopii tekstury
    koszulki i deformuje się razem z nią bez dodatkowej siatki. Dotychczasowa
    poza bazowa, proceduralne ruchy, trzy wślizgi i powstawanie po upadku
    pozostają dostępne.
  • Po straconej bramce zawodnik z pola losuje deterministycznie spośród
    trzech dotychczasowych reakcji oraz sześciu nowych wariantów angry,
    complain i cry. run zastępuje proceduralny krok dopiero przy ruchu na co
    najmniej cztery pola liczonym odległością Czebyszewa; krótszy ruch
    zachowuje poprzednią animację. Błędny osadzony take idle, który zawiera
    pozę wiązania, jest bezwarunkowo odrzucany, a okresowe urozmaicenie
    bezruchu losuje wyłącznie dwa bezpieczne idles proceduralne. Graniczne
    klatki pozostałych siedmiu nowych klipów są pomijane, więc żadna z
    używanych animacji nie wchodzi ani nie zatrzymuje zawodnika w T-pose.
  • Identyfikator zgodności klienta został podbity, aby gracze sieciowi
    korzystali z tej samej puli reakcji i progu animacji ruchu.

Kamera 3D skupiona na żonglującym zawodniku
-------------------------------------------
19.08.2026, 11:45

  Poprawki:
  • W widoku 3D żonglujący zawodnik ma najwyższy priorytet śledzenia, więc
    kamera pozostaje skupiona na postaci zamiast podążać za animowaną piłką
    lub innym awaryjnym celem kadru. Specjalny fokus znika, gdy piłka
    rozpoczyna podanie lub strzał.

Narodowe banery kibiców na obu trybunach
----------------------------------------
19.08.2026, 10:43

  • Każdy mecz dekoruje obie trybuny sześcioma bezkolizyjnymi adboardami w
    paletach grających reprezentacji. Drużyny występują naprzemiennie po obu
    stronach stadionu, a każda otrzymuje trzy własne hasła kibicowskie w
    języku narodowym. Jednostronne płaskie panele stoją pionowo na poziomie
    murawy, bezpośrednio przed porcelanowym rantem, więc od strony boiska
    kolejność to adboard, rant i trybuny; oglądane od tyłu znikają wraz z
    napisem zamiast odsłaniać czarną obudowę. World-space UI dobiera napis
    tak, by duże litery wypełniały wysokość panelu; fallback czcionki
    zachowuje znaki diakrytyczne.
  • Zestaw obejmuje wszystkie 14 reprezentacji; drużyny wielojęzyczne
    korzystają z rozpoznawalnych haseł w kilku językach urzędowych, a
    marokańskie z powszechnie zapisywanej alfabetem łacińskim dariji, dzięki
    czemu tekst nie traci poprawnego kierunku ani łączenia znaków w prostym
    rendererze 3D.

Stylizowane niebo widoczne podczas powtórek bramek
--------------------------------------------------
19.08.2026, 10:24

  Poprawki:
  • Kamera powtórki nie zastępuje już nieba jednolitym granatowo-czarnym tłem.
    Na czas obu ujęć przejmuje istniejące niebo meczu wraz z gradientem,
    chmurami, słońcem i post-processingiem, a po zakończeniu oddaje je kamerze
    rozgrywki bez przebudowy chmur ani resetowania biegu dnia.

Skrypt budowania podąża za wersją edytora z projektu
----------------------------------------------------
19.08.2026, 10:03

  Poprawki:
  • Tools/build-and-deploy.sh miał ścieżkę do edytora wpisaną na sztywno, więc
    po podbiciu projektu na Unity 6000.5.9f1 uruchomienie kończyło się od razu
    komunikatem, że Unity nie ma pod starą ścieżką. Binarka jest teraz
    wyliczana z ProjectSettings/ProjectVersion.txt: najpierw sprawdzany jest
    układ katalogów Huba, a gdy edytor stoi gdzie indziej, jego lokalizację
    podaje unity --json editors. Zmienna UNITY_PATH ze środowiska nadal
    nadpisuje jedno i drugie, a nieudane rozpoznanie kończy się błędem z
    wersją i podpowiedzią, zamiast wchodzić w budowanie. Baner uruchomienia
    pokazuje obok ścieżki użytą wersję.
  • Projekt jest podbity do Unity 6000.5.9f1, wraz z pakietami Collaborate
    2.13.6 i Netcode for GameObjects 2.13.1, które edytor przeliczył przy tej
    wersji.
  • AGENTS.md opisuje dostępne w systemie CLI unity
    (/Users/siano/.unity/bin/unity): polecenia wyłącznie odczytujące stan
    środowiska są dozwolone bez pytania, natomiast build, run, open, test,
    pipeline install, mcp configure i bug wymagają zgody użytkownika, bo
    uruchamiają edytor albo zmieniają projekt. Odnośniki do wersji edytora w
    AGENTS.md i DEPLOY_BUILDS_INSTRUCTIONS.md wskazują teraz na plik z
    przypiętą wersją zamiast powtarzać numer.

Eksport iOS nie linkuje już obiektów tvOS
-----------------------------------------
05.08.2026, 20:18

  Poprawki:
  • Eksport iPadOS potrafił dostać do lib_burst_generated.a obiekty
    skompilowane dla tvOS, przez co Xcode odmawiał budowy .ipa komunikatem
    Building for 'iOS', but linking in object file built for 'tvOS'. Obie
    platformy Apple celują w ARM, a cache Burst rozróżnia je na tyle słabo, że
    wynik jednej trafiał do drugiej. Cache obu celów, ich pliki
    AotSettings_*.hash oraz katalog pośredni Temp/Burst są teraz czyszczone
    przed każdym eksportem Apple, a nie tylko przed tvOS — platforma, która
    budowała się jako ostatnia, zostawiała swoje obiekty następnemu
    uruchomieniu, więc trucizna trafiała w ten eksport, który startuje
    pierwszy.

Prawdziwe średnie w rankingu ELO
--------------------------------
05.08.2026, 19:37

  Poprawki:
  • Kolumny ŚR. POZYCJA i ŚR. RANKING na stronie statystyk i w rankingu w grze
    pokazywały aktualne miejsce oraz aktualne punkty, więc gracz, który był
    kiedyś pierwszy, a potem spadł na drugie miejsce, widział średnią pozycję
    2.0. Obie liczby są teraz średnimi z całej historii: przy przeliczaniu
    rankingu po każdym meczu zapisywane jest zdjęcie tabeli, a pozycja i
    ranking każdego notowanego gracza wpadają do jego sum. Próbkowani są
    wszyscy gracze, nie tylko uczestnicy meczu, bo cudzy wynik też przesuwa
    tabelę; gracz liczy się od swojego pierwszego meczu. Format odpowiedzi API
    i widok klienta pozostają bez zmian.

Nowa kolejność budowania i równoległa wysyłka paczek
----------------------------------------------------
05.08.2026, 19:24

  • Tools/build-and-deploy.sh buduje platformy w kolejności iOS, macOS,
    Windows, tvOS. Eksport iPadOS wykonuje się jako pierwszy, więc paczki
    macOS i Windows powstają później i mają czas na transfer, a eksport tvOS
    zamyka bieg, zachowując czyszczenie cache Burst tuż przed sobą.
  • Wysyłka na serwer nie jest już osobnym etapem po wszystkich buildach:
    każda gotowa paczka trafia do zadania w tle zaraz po spakowaniu, więc
    transfer jednej platformy nakłada się na budowanie następnej. W tle
    wysyłane są też metadane, changelog strony i znacznik tvOS, a przełączenie
    edytora z powrotem na profil macOS wykonuje się przed odebraniem
    transferów, żeby ostatnia wysyłka nakładała się i na nie.
  • Postęp wysyłek pokazuje panel przypięty na stałe do dołu terminala: wiersz
    na każdy trwający transfer z etykietą platformy, paskiem, procentem,
    liczbą wysłanych megabajtów, prędkością i szacowanym czasem, odświeżany co
    sekundę. Wyjście budowania przewija się nad panelem i nigdy go nie
    nadpisuje, bo skrypt zawęża obszar przewijania terminala o wysokość
    panelu, a po zakończeniu wysyłek zdejmuje panel i przywraca pełną
    wysokość. Po przejściu kontroli wstępnych skrypt czyści ekran i zajmuje
    okno w całości: baner startowy ląduje w górnym wierszu, a przebieg
    wypełnia okno w dół, zamiast zaczynać się w dolnej linii nad resztkami
    poprzedniego uruchomienia. Nie jest do tego używany bufor alternatywny,
    więc log przebiegu zostaje w historii przewijania po zakończeniu skryptu.
    Zakończony transfer znika z panelu i zostawia w logu jedną trwałą linię ze
    swoim łącznym czasem. Wąski terminal skraca pasek i pomija kolejne pola
    zamiast ucinać wiersz.
  • Wypisywanie na terminal jest serializowane muteksem, ponieważ piszą do
    niego równolegle: pierwszy plan, każdy proces wysyłki i proces
    odrysowujący panel. Bez tego linia builda potrafiła trafić w obszar panelu
    i zniknąć przy najbliższym odrysowaniu. Kursor jest po każdym odrysowaniu
    parkowany w ostatnim wierszu obszaru przewijania, więc ewentualne
    zakłócenie samo się naprawia zamiast utrwalać.
  • Panel włącza się tylko na prawdziwym, dostatecznie wysokim terminalu. Przy
    przekierowaniu wyjścia do pliku, w logu CI albo po podaniu --plain skrypt
    wraca do zwykłych linii postępu wypisywanych co dziesięć sekund, bez
    sekwencji sterujących w logu. Postęp pochodzi z rsync --info=progress2,
    którego zapis z powrotami karetki jest rozbijany na rekordy przy odczycie
    z logu.
  • Skrypt kończy się dopiero po zebraniu wszystkich zadań wysyłki.
    Niepowodzenie transferu przerywa bieg z kodem błędu i wypisuje ogon logu
    danego transferu; logi transferów leżą w Build/upload-logs/. Przerwanie
    skryptu albo błąd builda zabija zadania wysyłki razem z ich procesami
    rsync, zamiast zostawiać je odłączone.
  • Połączenie SSH jest sprawdzane przed pierwszym buildem, a nie przed
    pierwszą wysyłką, więc nieosiągalny serwer zatrzymuje bieg zanim Unity
    zacznie pracę. Transfery działają z odłączonym stdin, żeby ssh w tle nie
    przechwycił terminala prośbą o hasło do klucza, i bez kompresji, bo paczki
    są już spakowane; --partial --inplace pozwala wznowić przerwany transfer
    zamiast wysyłać wszystko od nowa.

Wielowarstwowa panorama dolnośląskiego stadionu
-----------------------------------------------
05.08.2026, 14:21

  • Stadion otacza statyczna panorama 360° zakotwiczona we wspólnym
    StadiumCenter: cztery fizycznie rozdzielone pierścienie tworzą dalekie
    wzgórza i pola, miasteczko z czerwonymi dachami i dominantami, bliższy pas
    drzew oraz pojedynczy detal przemysłowy. Promienie 320/250/200/170
    jednostek odsuwają krajobraz daleko od trybun i zapewniają spokojniejszą
    paralaksę przy obrocie wszystkich kamer. Wzgórza, miasto i drzewa używają
    poziomego tilingu 1,65, więc domy, wieże i korony zajmują mniejszy kąt
    widzenia zamiast pozostawać tej samej szerokości po samym zwiększeniu
    promienia; wysokości 72/64/47/40 dodatkowo zmniejszają ich skalę pionową.
    Pionowa baza jest liczona dopiero z gotowej dolnej krawędzi stołu i
    domyślnie chowana o 56 komórek, aby kompensować optyczne podnoszenie
    podstawy odległych obiektów w projekcji perspektywicznej. Krajobraz
    dochodzi dzięki temu za drewno bez jasnego pasa między teksturą a blatem,
    przede wszystkim w dwóch prześwitach przy krótszych bokach boiska, a
    margines pozostaje regulowany w inspektorze TabletopEnvironment.
  • Każda warstwa używa jednego zakrzywionego mesha i jednego renderera z
    submeshem na segment. Deterministyczny układ obsługuje stałe ziarno,
    warianty tekstur, odbicie, tiling, skalę i offset UV, mieszanie bez
    identycznych sąsiadów oraz ręczne nadpisanie albo wyłączenie każdego
    segmentu; gotowy preset Lower Silesian Small Town ładuje dostarczone,
    przycięte tekstury z Resources i oszczędnie pokazuje detal przemysłowy
    tylko w jednym wycinku horyzontu.
  • Dedykowany shader URP TacticsFootball/StadiumPanorama jest nieoświetlony,
    nie rzuca ani nie odbiera cieni, nie zapisuje głębi i łączy alpha clipping
    z przezroczystością. Sąsiednie wycinki każdego pierścienia zachodzą na
    siebie o cztery stopnie i miękko wygaszają krawędzie przez drugi kanał UV,
    dzięki czemu osie obu bramek nie odsłaniają pionowej szczeliny na granicy
    segmentów. Kolejki rysują plany od wzgórz do detali bez z-fightingu, a
    tint, nasycenie, krycie i zamglenie materiałowe realizują perspektywę
    atmosferyczną bez zmiany globalnej mgły sceny.
  • Inspektor i menu edytora udostępniają generowanie, regenerację układu,
    czyszczenie, ponowne zastosowanie presetu oraz tekstowy podgląd ziarna.
    Generowanie jest idempotentne, obrysy dolnej i górnej krawędzi każdego
    pierścienia są widoczne przez Gizmos, a panorama nie ma pętli
    aktualizacji, colliderów ani brył fizycznych.
  • Skrypt przygotowania assetów przycina przezroczyste źródła do samych pasów
    krajobrazu. Testy statyczne obejmują pojedynczą hierarchię czterech
    warstw, brak komponentów fizycznych, jeden renderer na plan, nakładające
    się i wygaszane meshe 360°, minimalne średnice i wysokości odsuniętych
    pierścieni, rosnące kolejki renderowania oraz powtarzalny układ dla tego
    samego ziarna. Test projekcji ekranowej odtwarza trzy zoomy kamery zza
    zawodnika w czterech kierunkach i wymaga, aby podstawy wzgórz, miasta i
    drzew pozostały poniżej widocznej krawędzi stołu, a ich korony nadal
    wystawały ponad nią; test stołu niezależnie sprawdza bazę poniżej gotowych
    boundsów i mierzy wyłącznie fizyczne trybuny.

Grube wełniane getry wszystkich reprezentacji
---------------------------------------------
05.08.2026, 12:58

  • Getry zawodników każdej reprezentacji, zarówno w kompletach domowych, jak
    i wyjazdowych, korzystają z tej samej neutralnej powierzchni grubej wełny
    i mapy reliefu co getry oraz rękawice bramkarza. Każda goleń otrzymuje
    ciągłą projekcję UV na całej szerokości i wysokości getry; dedykowana
    projekcja argentyńskiej koszulki nadpisuje wyłącznie tułów i rękawy, nie
    kasując już współrzędnych wełny. Materiał zachowuje właściwy kolor stroju,
    a specjalne wzory Norwegii pozostają nałożone na identyczny wełniany
    relief.
  • Test materiału obejmuje zwykły komplet Polski, domową Argentynę oraz
    wyjazdową Norwegię i sprawdza neutralny splot, mapę normalną, matowe
    wykończenie oraz rozpiętość projekcji getrów w obu osiach.

Gładki domowy strój Argentyny
-----------------------------
05.08.2026, 11:20

  • Argentyńscy zawodnicy z pola korzystają w domowym komplecie z osobnej,
    gładkiej powierzchni koszulki: biała baza jest opasana regularnymi
    błękitnymi pasami, a rękawy mają trzy granatowe paski oraz ciemne
    mankiety. Tułów i rękawy otrzymują oddzielne obszary ciągłej projekcji UV,
    dzięki czemu linie płynnie przylegają do obłego, animowanego modelu
    zamiast powstawać z osobnych brył albo granic trójkątów.
  • Atlas zawiera wyłącznie barwy i paski. Nie ma herbu federacji, tarczy
    FIFA, znaku Adidasa ani innego logo, a jednolite albedo bez mapy normalnej
    zachowuje plastelinkowy styl postaci. Strój wyjazdowy, bramkarz, ciemne
    spodenki, białe getry oraz argentyński krój numerów pozostają bez zmian.
  • Test modelu sprawdza użycie dedykowanego atlasu i oświetlanego materiału,
    brak reliefu, neutralny biały mnożnik zachowywany przez prezentację oraz
    brak obiektów oznaczeń federacji i producentów.

Jednoznaczna klasyfikacja poprawek w changelogach
-------------------------------------------------
05.08.2026, 07:15

  • Instrukcje repozytorium definiują teraz Fixed i Poprawki wyłącznie jako
    naprawy błędów istniejących przed rozpoczęciem danego zadania. Iteracje,
    regresje i nietrafione rozwiązania powstałe podczas tworzenia tej samej
    funkcji albo assetu mają zniknąć z opisu przebiegu prac, a wpis
    przedstawiać wyłącznie poprawny rezultat końcowy w sekcji zmian.
  • Wczorajszy wpis norweskiego stroju został sprowadzony do końcowego efektu
    zadania; usunięto z niego sztuczny podział na zmianę i poprawki kolejnych
    wersji tej samej implementacji. Analogicznie oczyszczono przeznaczony dla
    graczy punkt z 4 sierpnia.

Dopracowany norweski strój domowy parówczaka
--------------------------------------------
04.08.2026, 21:44

  • Główny, animowany model norweskiego zawodnika z pola nosi teraz czerwony
    komplet inspirowany dostarczonym projektem: wysoko poprowadzony granatowy
    krzyż ma proporcjonalnie wąski granatowy rdzeń, czyste białe obramowanie i
    pion przesunięty na prawą pierś zawodnika, spodenki węższe boczne pasy, a
    getry dwukolorowe opaski. Koszulka korzysta z cylindrycznej projekcji UV
    otulającej obły tułów i barki, ale poziome ramię krzyża jest ograniczone
    do przodu, więc plecy pod numerem pozostają czerwone. Biały mnożnik
    prekolorowanego materiału pozostaje zachowany podczas prezentacji,
    przyciemnienia aktywowanego zawodnika i zmian tury.
  • Koszulka i spodenki mają jednolite kolory bez splotu zapisanego w albedo i
    bez mapy normalnej, dzięki czemu zachowują absolutnie gładką,
    plastelinkową powierzchnię; delikatny połysk wynika wyłącznie z ich obłej
    geometrii. Duży ornament z dostarczonego źródła pozostaje widoczny jako
    subtelnie jaśniejszy kolor wewnątrz granatowego krzyża, bez fizycznego
    reliefu. Tarcza zawodnika z pola jest wypalona bezpośrednio w tej samej
    gładkiej teksturze i wycentrowana na wysokości poziomego pasa. Getry
    korzystają z grubej wełnianej powierzchni, rękawy kończą się w połowie
    ramienia, a numer w dokładnym kroju Norway2026Digits.png jest rzutowany
    gęstą siatką na faktycznie zdeformowaną powierzchnię pleców. Komplet nie
    zawiera logo Nike ani innego znaku producenta.
  • Szczegółowy wzór jest ograniczony do domowego kompletu Norwegii i
    zawodników z pola. Bramkarz oraz norweski strój wyjazdowy zachowują swoje
    dotychczasowe materiały, a pozostałe reprezentacje nadal korzystają z
    ośmiu wspólnych stref stroju.
  • Norweski bramkarz zachowuje cały dotychczasowy ciemny komplet, jego
    podział i materiały, ale otrzymuje tarczę reprezentacji na piersi oraz
    numer w norweskim kroju na plecach. Bramkarze pozostałych reprezentacji
    nadal używają standardowych cyfr i nie dostają norweskiej tarczy.
  • Testy assetów sprawdzają brak dodatkowych stref trójkątów, osobnej
    nakładki herbu i map normalnych na gładkiej koszulce oraz spodenkach
    zawodnika z pola, ich plastelinkową gładkość, wełnianą mapę normalną
    getrów, trwały biały mnożnik, przypisanie trzech tekstur stroju, użycie
    norweskiego atlasu cyfr, zachowanie materiału bramkarza oraz gęstą
    geometrię jego tarczy i numerów dopasowaną do powierzchni zawodnika.

Ustawienia lokalnego meczu w GameBootstrap
------------------------------------------
04.08.2026, 20:51

  • Inspector GameBootstrap pozwala przed bezpośrednim uruchomieniem sceny
    Game wybrać z list z polskimi nazwami drużynę gracza i komputera, ustawić
    liczbę goli do zwycięstwa oraz opcjonalne stałe ziarno losowania.
  • Ustawienia podglądu lokalnego są włączane osobnym przełącznikiem. Gdy
    pozostaje wyłączony, scena zachowuje wybór z menu; mecze sieciowe i
    powtórki zawsze korzystają ze swoich danych.
  • Pola planszy i ruchu mają w dedykowanym Inspectorze polskie, pogrupowane
    etykiety oraz objaśnienie zakresu konfiguracji lokalnego startu.

Stylizowane niebo: gradient, chmury, słońce i atmosfera
-------------------------------------------------------
04.08.2026, 18:52

  • Widok meczu ma proceduralny skybox TacticsFootball/StylizedSky: pionowy
    gradient od głębokiego błękitu w zenicie do jasnego przy horyzoncie, z
    osobnym, wąskim rozjaśnieniem tuż nad linią horyzontu i miękkim przejściem
    w kolor pod nią. Wszystkie barwy, wykładnik gradientu i szerokość poświaty
    są polami w inspektorze. Zastąpił on doklejany do kamery quad SkyBackdrop,
    który został usunięty razem z obsługą jego skalowania w kontrolerze
    kamery.
  • Nad boiskiem przesuwają się chmury: billboardy z czterema teksturami PNG z
    katalogu Resources/Textures/Sky/Clouds (osobnego, żeby losowanie tekstury
    chmury nie sięgnęło po grafikę słońca), ustawiane raz i już tylko
    przemieszczane. Każda dostaje z ziarna losową teksturę, rozmiar, wysokość,
    odbicie poziome i prędkość, a ruch to bardzo powolny obrót azymutu, więc
    chmura schodząca z jednej krawędzi wraca drugą bez skoku i bez tworzenia
    obiektów w czasie gry. Warstwy różnicują wysokość, rozmiar, tempo i
    krycie.
  • Chmury i słońce leżą na panoramie, a nie na rzucie kierunku na płaszczyznę
    kamery: wysokość na ekranie wynika wyłącznie z elewacji, a pozycja pozioma
    wyłącznie z azymutu względem kamery. Punkt nieba trzyma więc swoją
    wysokość niezależnie od obrotu kamery, a obrót jedynie przewija niebo na
    boki. Poprzedni rzut mieszał obie osie różnymi skalami — poziom
    szerokością kadru, pion wysokością — przez co obiekt o stałym kierunku
    pozornie wznosił się i opadał przy obrocie kamery. Horyzont leży teraz na
    stałej linii kadru, więc wszystko powyżej niej rysuje się nad boiskiem.
    Dodatkowo billboardy są rysowane daleko, więc test głębi chowa je za
    boiskiem i trybunami, a interfejs jest nakładką ekranową i nigdy nie jest
    przykryty. Przy widoku z góry billboardy są wyłączane.
  • Na niebie widać słońce: jasna tarcza z delikatną, addytywną poświatą,
    wędrująca własnym łukiem od wschodu do zachodu. Pełna doba trwa tyle, co
    mecz — domyślnie 45 minut — a łuk jest zakotwiczony w świecie, więc obrót
    kamery przesuwa słońce po kadrze zamiast je ze sobą nieść. Ruch nie dotyka
    oświetlenia sceny: świeci wyłącznie billboard. Poniżej horyzontu tarcza
    jest chowana, przez co przeskok z zachodu do kolejnego wschodu pozostaje
    niewidoczny. Maksymalna wysokość łuku jest domyślnie ograniczona do 36°,
    bo kamera meczu patrzy w dół pod kątem 35° i wyżej położone niebo ma już
    za plecami. Pole Follow Key Light przywraca dawne zachowanie, w którym
    tarcza trzyma się kierunku głównego światła. Tarcza nosi rysunek z
    Resources/Textures/Sky/SunFace — rozeźloną, żartobliwą minę — a gdy tego
    pliku brakuje, rysowany jest gładki dysk generowany proceduralnie; pole w
    inspektorze pozwala wskazać dowolną inną teksturę.
    Tools/make-sun-texture.py przygotowuje taką grafikę z obrazu na czarnym
    tle: lokalizuje tarczę po jasności, wycina ją jako koło z miękką krawędzią
    i zapisuje kwadratowy sprite. Alfa celowo nie idzie za jasnością, bo wtedy
    ciemne oczy i zęby stałyby się dziurami, przez które widać niebo. Poświata
    jest w cieplejszym, pomarańczowym tonie pasującym do tarczy, w mocy
    dobranej pod jasne niebo: sam bloom rozświetla wyłącznie to, co przekracza
    próg jasności murawy i strojów, czyli tylko tarczę.
  • Atmosfera: liniowa mgła w kolorze horyzontu, włączana od 55 jednostek,
    więc dotyka tylko dalekiego planu, oraz bloom o progu powyżej jasności
    murawy i strojów, przez co świeci wyłącznie słońce. Bloom działa przez
    własny profil wolumenu i włącza post-processing tylko na kamerze meczu.
  • Całość konfiguruje jeden komponent StylizedSkyController z sensownymi
    wartościami domyślnymi, przyciskiem generowania obiektów w inspektorze i
    pozycją w menu GameObject ▸ TacticsFootball ▸ Stylized Sky.

Trybuny po obu stronach boiska
------------------------------
04.08.2026, 18:32

  • Widok meczu stawia teraz dwie trybuny: Stand_Far przy dalszym dłuższym
    boku i Stand_Near przy bliższym, obrócona o 180 stopni wokół planszy, więc
    obie patrzą na siebie przez boisko. Dopasowanie jest liczone raz, z modelu
    zmierzonego przed ustawieniem, i stosowane do obu stron, więc długość,
    lico fartucha z obudową i zanurzenie porcelany są identyczne.
  • Blat stołu obejmuje sumę obrysów obu trybun, więc poszerza się teraz w
    obie strony i żadna z nich nie wystaje poza drewno.
  • Nazwa trybuny wchodzi do ziarna wariacji ławek, więc druga trybuna zużywa
    się inaczej, zamiast powtarzać deska w deskę układ pierwszej.

Rekordy z graczem, który je ustanowił
-------------------------------------
03.08.2026, 20:05

  • Tabela rekordów pokazuje przy zawodniku gracza, na którego koncie padł
    rekord: „AJER (LALI)”. Dotyczy to zarówno strony statystyk w lobby, jak i
    ekranu rekordów w grze, w obu zakresach — sieciowym i lokalnym.
  • Rekordy samego meczu (najkrótszy, najdłuższy, najmniej i najwięcej tur) są
    już przypisane do osoby, więc zostają samą nazwą gracza, bez nawiasu.
  • Zapytanie o rekordy zwraca teraz obok nazwiska zawodnika także nazwę
    gracza po tej stronie meczu (player), a rekordy z lokalnego archiwum
    wypełniają to pole nazwą gospodarza albo gościa danego spotkania.

Czytelne kolory nazw w pasku komentarza
---------------------------------------
03.08.2026, 19:32

  Poprawki:
  • Nazwiska, numery na koszulkach i nazwy reprezentacji w pasku komentarza
    dobierają kolor na podstawie kontrastu luminancji (WCAG) względem tła
    paska, a nie odległości w RGB. Wcześniej ciemnoczerwony akcent na
    pomarańczowym pasku Holandii przechodził test jako „inny kolor” i był
    nieczytelny.
  • Jeżeli żaden z kolorów kompletu (koszulka, wykończenie, kolor powiadomień)
    nie osiąga kontrastu 3:1 wobec tła, najlepszy z nich jest przyciemniany
    albo rozjaśniany aż do progu, więc akcent zawsze pozostaje widoczny —
    również gdy pasek należy do tej samej reprezentacji co wyróżniane słowo.
  • Nazwa reprezentacji nie jest już pomijana przy kolorowaniu, gdy zbytnio
    przypomina tło; dostaje skorygowany odcień zamiast zostać w kolorze
    zwykłego tekstu.

Punkty rankingowe w raporcie meczu sieciowego
---------------------------------------------
03.08.2026, 19:26

  • Raport meczu otwierany z historii spotkań sieciowych pokazuje pod nazwą
    każdej reprezentacji punkty rankingowe zdobyte albo stracone w tym meczu,
    tak samo jak strona meczu w lobby: na zielono przy zysku, na czerwono przy
    stracie.
  • Wyliczenie jest powtórzeniem wzoru serwera (server/lobby/elo.go): obaj
    gracze są liczeni od bazowych 1000 punktów, oczekiwany wynik korygują siły
    reprezentacji, a współczynnik K wynosi 32. Dzięki temu klient nie
    potrzebuje dodatkowego zapytania, a liczba zgadza się z tą na stronie.
  • Raporty meczów lokalnych oraz ekran po zakończonym meczu punktów nie
    pokazują — ranking dotyczy wyłącznie rozgrywki sieciowej.

Beton trybuny z kruszywem
-------------------------
01.08.2026, 20:52

  • Stopnie i fartuch trybuny korzystają z tekstury gravel_embedded_concrete
    zamiast concrete_floor_worn: beton ma widoczne kruszywo, tiling wrócił do
    1 zamiast sześciokrotnego powtórzenia, a mapa wysokości i parallaks
    zostały wyłączone na rzecz samej normalnej o łagodniejszej sile.
  • Z repozytorium usunięto stary komplet tekstur betonu oraz nieużywane mapy
    wysokości i szorstkości nowego kompletu; w projekcie zostają wyłącznie
    pliki, do których materiały faktycznie się odwołują.

Ławki trybuny w wyblakłym błękicie ZKS Polar
--------------------------------------------
01.08.2026, 20:24

  • Siatki ławek trybuny są rozdzielane w czasie działania gry na pojedyncze
    deski: wierzchołki są najpierw sklejane po pozycji (importer rozbija je po
    normalnych), a spójne kawałki trafiają do osobnych rendererów
    współdzielących ten sam materiał.
  • Każda deska dostaje własne przesunięcie i własne skalowanie _BaseMap_ST —
    z opcjonalnym odbiciem lustrzanym, które rozbija powtarzalność wzoru bez
    drugiej tekstury — oraz własny odcień i jasność farby, ustawiane przez
    MaterialPropertyBlock. Materiał nie jest kopiowany ani modyfikowany, więc
    nadal jest jedną instancją dla całej trybuny.
  • Wartości wynikają z deterministycznego skrótu nazwy obiektu i pozycji
    deski, więc wygląd trybuny jest identyczny przy każdym uruchomieniu i u
    obu graczy w meczu sieciowym.
  • Zakresy przesunięcia i skalowania tekstury, przełącznik odbicia
    lustrzanego, zakresy barwy, nasycenia i jasności, filtr nazw rendererów
    oraz przełącznik samego podziału na deski są polami w inspektorze
    komponentu.
  • Ławki są pomalowane błękitem z herbu ZKS Polar. Sam tint tego nie osiągał:
    tekstura jest w każdym miejscu uboga w kanał niebieski, więc mnożnik dość
    mocny, by dać błękit, wybielał też odsłonięte drewno. Farba jest więc
    przemalowana wprost w teksturze bazowej przez
    Tools/make-bench-paint-texture.py, który rozdziela farbę od drewna po
    ciepłocie piksela (różnicy czerwonego i niebieskiego) miękką maską i
    podmienia wyłącznie barwę farby, zachowując jej światłocień, przetarcia i
    ciepłe drewno.
  • Zakresy wariacji zostały przez to złagodzone: tint tylko delikatnie
    przechyla każdą deskę ku morskiemu albo granatowemu i różnicuje jasność,
    zamiast tworzyć kolor od zera.
  • Materiał ławek korzysta z wygenerowanej tekstury
    BenchPaintPolarBlue_diff_1k, a jego kolor bazowy jest prawie neutralny.
    Model trybuny ma włączony odczyt siatki, bez którego podziału na deski nie
    da się wykonać w graczu.

Trybuna wokół stołowego boiska
------------------------------
01.08.2026, 19:06

  • Widok meczu buduje teraz trybunę: model Resources/Models/Stadium jest
    wstawiany przez nowy StadiumEnvironment i dopasowywany wyłącznie z
    pomiarów gotowej planszy, bez ręcznych wartości w scenie. Prosta środkowa
    część trybuny (Main_*) dostaje długość dłuższego boku porcelanowej
    obudowy, a ramiona i łuki rozchodzą się poza narożniki.
  • Ustawienie trybuny nie zakłada żadnej konwencji osi importera: kierunek „w
    górę” wynika z tego, że płyta trybuny jest cienka wzdłuż tej osi i kolejne
    rzędy po niej rosną, a kierunek „w tył” z położenia wału ziemnego względem
    fartucha od strony boiska. Dzięki temu model nie wymaga ręcznego obrotu
    ani skali w scenie.
  • Wysokości są przeliczane tak, że fartuch Main_Front_Apron licuje się
    dokładnie z górną krawędzią FieldBoardBase: pierwszy rząd trybuny zaczyna
    się na poziomie murawy, a nie stopień niżej. Porcelanowa obudowa jest przy
    tym wtopiona w fartuch na 0,35 komórki. Zanurzenie, długość i wysokość
    względem obudowy można korygować polami w inspektorze.
  • Blat stołu podnosi się do podstawy tak ustawionej trybuny, więc pod
    trybuną nie ma szczeliny, a porcelanowa obudowa zanurza się w drewnie.
    Blat jest też pogrubiany na tyle, aby obudowa nie wystawała spodem, i
    wymiarowany tak, by objąć zarówno planszę, jak i cały obrys trybuny z
    marginesem.
  • Trybuna jest wyłącznie dekoracją: instancja traci kolidery, nie rzuca
    cieni na murawę i nie staje się rodzicem żadnego obiektu rozgrywki.
  • Model przeniesiono do Assets/Resources/Models/Stadium.fbx (wczytywany po
    ścieżce), a jego materiały i tekstury do Assets/Art/Models/Stadium/,
    ponieważ nie są ładowane przez Resources.Load. Usunięto zdublowane
    materiały *.002, a import wskazuje teraz oteksturowany Concrete.
  • Z Game.unity usunięto ręcznie wstawioną instancję modelu — scena meczu
    powstaje w całości w czasie działania gry.

Bramkarz zawsze wraca do właściwego idle
----------------------------------------
30.07.2026, 20:29

  Poprawki:
  • Usunięto stan zatrzymujący bramkarza na pośredniej klatce parady. Zarówno
    podczas zwykłej gry, po golu, jak i w powtórce bramkarz zawsze odtwarza
    pełną fazę powrotu, przywraca pozycję wyjściową i natychmiast przechodzi
    do pozy wymaganej przez bieżącą sytuację: gotowości na linii, idle
    zagrożenia albo Happy Idle.
  • Mecz i powtórka nie przekazują już do animacji parady flagi, która mogła
    zablokować późniejsze próbkowanie idle. UUID klienta został podbity, aby
    obie strony meczu sieciowego korzystały z tego samego przebiegu animacji.
  • Idle zagrożenia zależy ponownie od położenia rywala posiadającego piłkę, a
    nie od dowolnego zawodnika bez piłki. Gdy piłka pozostaje na przeciwnej
    połowie, bramkarz korzysta z Happy Idle; symulator meczu zapisuje ten sam
    warunek w śladzie animacji.

Niecelne strzały mogą przelecieć nad bramką
-------------------------------------------
30.07.2026, 19:51

  • Wyraźnie przegrane rzuty celności dzielą się teraz deterministycznie
    pomiędzy pudło obok bramki i nowy wariant High, który prowadzi piłkę ponad
    poprzeczką. Podział korzysta z istniejącego hasha strzału i nie zużywa
    dodatkowego losowania, więc całkowita celność oraz udział pudeł od
    obramowania pozostają bez zmian.
  • Wysokie pudło kończy lot w punkcie za linią i co najmniej 0,72 jednostki
    ponad poprzeczką, po czym schodzi na deterministyczne pole poza światłem
    bramki. Ma własną podpowiedź oraz pulę komentarzy, w tym „Panu Bogu w
    okno”.
  • Testy regresji wymagają obu wariantów ciężkiego pudła oraz potwierdzają,
    że żaden z nich nie zapisze luźnej piłki wewnątrz światła bramki. UUID
    klienta został podbity, ponieważ nowy podtyp jest częścią
    deterministycznego wyniku odtwarzanego przez obie strony meczu sieciowego.

Naturalniejsze reakcje zawodników po golu
-----------------------------------------
30.07.2026, 19:48

  Poprawki:
  • Wariant rozczarowania zakończony upadkiem nie obraca już całej sylwetki
    jak jednej sztywnej bryły. Deterministyczna sekwencja ugina uda, łydki i
    stopy, przechyla tułów z lekkim bocznym skrętem oraz ustawia barki, łokcie
    i głowę do amortyzacji kontaktu z murawą.
  • Podczas piruetu „samolot” ramiona są liczone względem aktualnie obróconej
    klatki piersiowej, a przedramiona zachowują naturalną relację do barków.
    Obrót nie wykręca już rąk wokół tułowia.

Odbity strzał trafia bramkarza w głowę
--------------------------------------
30.07.2026, 19:21

  Poprawki:
  • Strzał rozstrzygnięty jako Deflected leci teraz do animowanej pozycji
    głowy bramkarza, uruchamia dźwięk kontaktu i proceduralny odrzut głowy, a
    następnie odbija się do dokładnego pola luźnej piłki wyznaczonego przez
    rdzeń. Bramkarz nie wykonuje przy tym niezwiązanej z kontaktem parady
    rękami, więc zdarzenie nie wygląda już jak odbicie od pustej przestrzeni
    albo bocznej siatki.
  • Komentarz i podpowiedź po akcji opisują obronę głową zamiast rękawic lub
    nieokreślonego odbicia. Ten sam tor obsługuje strzały gracza, komputera
    oraz lob zakończony odbiciem.

Bramkarz zostaje na murawie po straconym golu
---------------------------------------------
30.07.2026, 18:55

  Poprawki:
  • Parada zakończona golem zatrzymuje bramkarza w leżącej klatce wybranego
    Goalkeeper Diving Save przez celebrację oraz oba ujęcia powtórki. Reakcja
    rozczarowania nie nadpisuje tej pozy, a zwolnienie prezentacji przywraca
    zapisaną pozycję i cały szkielet przed dalszą grą.
  • Pudło albo skuteczna obrona nadal odtwarza pełne zakończenie parady i
    wraca do właściwego idle. StandingUp pozostaje zarezerwowane wyłącznie dla
    przewróconej ofiary skutecznego wślizgu.

Bramkarz zmienia domyślną pozę przy ataku
-----------------------------------------
30.07.2026, 12:41

  Poprawki:
  • Happy Idle jest zapętloną domyślną animacją bezczynności bramkarza.
    Dotychczasowy osadzony klip został usunięty ze zbiorczego GK_Paruwa.fbx i
    zastąpiony bezpośrednio dostarczonym Happy Idle-2.fbx z Character
    Arm-Space = 50; poza kontekstową korektą na linii bramkowej nie istnieje
    osobny klip ani stała warstwa korekty ramion.
  • Przy wejściu dowolnego zawodnika rywala na połowę bronioną przez bramkarza
    prefab wskazuje osadzone bezpośrednio w GK_Paruwa.fbx klipy Goalkeeper
    Idle i Goalkeeper Idle 2, zamiast osobnych FBX-ów retargetowanych w
    runtime; alert nie czeka wyłącznie na właściciela piłki. Po próbkowaniu
    klipu oba ramiona dostają subtelne, symetryczne rozszerzenie o 9 stopni.
  • Bramkarz ustawiony bezpośrednio na własnej linii bramkowej znów korzysta z
    pełnej, sprawdzonej dzień wcześniej UpdateGoalkeeperReadyPose, nadrzędnej
    wobec klipów FBX: ramiona mają rozstaw 62 stopni z ruchem ±22 stopnie, a
    nogi i tułów zachowują ugięcie oraz kołysanie. Po zejściu z linii wraca do
    idle właściwego dla bieżącej sytuacji.
  • Jeżeli klip zagrożenia mimo wszystko jest chwilowo niedostępny, bramkarz
    poza linią zachowuje niezmodyfikowany Happy Idle; szeroka, naprzemiennie
    machająca poza jest normalnym zachowaniem wyłącznie bezpośrednio na linii,
    a poza nią pozostaje ostatnim fallbackiem przy braku wszystkich klipów.
  • Generator prefabów najpierw sprawdza komplet klipów prezentacyjnych.
    Jeżeli Unity chwilowo nie udostępnia subassetu animacji podczas importu
    FBX-a, zachowuje ostatni poprawny prefab zamiast nadpisywać referencje
    animacji wartościami null.
  • Przywrócone zostały również zgubione przez ten sam import referencje
    parad, wykopu z ręki i odkładania piłki.
  • Instrukcje projektu wymagają odtąd aktualizacji docs/animacje.md przy
    każdej zmianie klipu, warunku uruchomienia, wariantu, fallbacku, timingu
    albo korekty pozy; sam dokument został uzupełniony o bieżące zasady Happy
    Idle i pozy zagrożenia.
  • UUID klienta został podbity, ponieważ zmieniły się domyślna animacja
    bramkarza i korekty pozy widoczne podczas wspólnych akcji meczu
    sieciowego.
  • StandingUp odtwarza wyłącznie przewrócona ofiara skutecznego wślizgu od
    tyłu. Klip został usunięty z zakończenia animacji wykonującego wślizg oraz
    z parady bramkarza, więc stojący zawodnik nie przechodzi już przez
    zdeformowaną fazę podnoszenia.
  • Wszystkie dedykowane klipy bramkarskie — parady, oba idle zagrożenia,
    podanie, kroki, chwyty, wykop i odkładanie piłki — są pobierane jako
    subassety bezpośrednio z GK_Paruwa.fbx. Prefab nie zależy już od osobnych
    FBX-ów, których lokalne identyfikatory klipu po restarcie Unity stawały
    się Missing; test assetów wymaga wspólnej ścieżki modelu dla każdej
    referencji bramkarza.
  • Wspólny reset pozy przywraca teraz pełny zapisany szkielet przed ręcznym
    ustawieniem nóg, rąk i roota. Zakończony StandingUp ani inny FBX nie może
    już zostawić zawodnikowi trwałego pochylenia kręgosłupa lub bioder; test
    regresji sprawdza odtworzenie obrotu każdej kości po próbkowaniu klipu.
  • Ręczna przebudowa prefabów nie usuwa już najpierw ostatnich poprawnych
    Parowczak i ParowczakKeeper. Jeżeli któryś FBX jest jeszcze importowany,
    gra zachowuje kompletne modele zamiast przechodzić na ludzkie sylwetki
    awaryjne.
  • Tools/simulate-ai-match.py --trace zapisuje po każdej aktywacji oczekiwaną
    animację bezczynności, pozycję i posiadanie piłki wszystkich ośmiu
    zawodników. Snapshot odwzorowuje priorytety PlayerView — w tym pełną pozę
    na linii, dwa warianty idle zagrożenia, Happy Idle, trzymanie piłki,
    żonglerkę i kontrolę podeszwą — dzięki czemu warunki przypisania animacji
    można sprawdzać bez uruchamiania Unity.
  • PlayerView ujawnia teraz żądaną i faktycznie zastosowaną animację
    bezczynności bramkarza. Nowy test tworzy runtime'owy model obu drużyn,
    porównuje wybór Happy Idle → Goalkeeper Idle/Goalkeeper Idle 2 →
    Goalkeeper Ready Pose i sprawdza, czy idle zagrożenia naprawdę zmienił
    kości ramion. Zapisany ParowczakKeeper otrzymał bezpośrednio poprawne
    identyfikatory subassetów z GK_Paruwa.fbx, więc nie wymaga kolejnej
    przebudowy, aby usunąć widoczne w Inspectorze wartości Missing.
  • Jeżeli ręcznie rozpoczęty import chwilowo nie udostępnia subassetu
    któregoś FBX-a, generator prefabów ponawia próbę co pół sekundy przez
    maksymalnie 30 sekund. Nie kończy już pracy po pierwszym komunikacie
    Animation clip unavailable, więc w ramach tej samej operacji tworzy
    poprawny ParowczakKeeper po zakończeniu importu; trwały brak assetu kończy
    się pojedynczym czytelnym błędem.
  • Generator prefabów nie uruchamia się już automatycznie przy starcie Unity
    ani po każdej rekompilacji skryptów. Ciężkie FBX-y są konfigurowane i
    przebudowywane wyłącznie po świadomym wybraniu Tactics Football > Rebuild
    Footballer Prefab; mechanizm ponawiania pozostaje częścią tej ręcznie
    rozpoczętej operacji.

Wślizg nie wyrzuca zawodnika z planszy
--------------------------------------
30.07.2026, 12:37

  Poprawki:
  • Wspólny odtwarzacz klipów zachowuje pozycję i skalę każdej kości modelu,
    nakładając z importowanego FBX-a wyłącznie obroty pozy. Translacja bioder
    i root motion zapisane przez Mixamo w innej skali nie mogą już przesunąć
    ani rozciągnąć zawodnika poza jego logiczne pole.
  • Test regresji próbkuje wszystkie trzy warianty wślizgu i sprawdza, że
    żaden z nich nie zmienia lokalnych pozycji ani skal szkieletu.

Przyznany gol zawsze wpada między słupkami
------------------------------------------
30.07.2026, 12:24

  Poprawki:
  • Prezentacja zwykłego, już rozstrzygniętego gola sprawdza teraz pozycję
    całego obwodu piłki w chwili przekroczenia linii. Strzał z ostrego kąta
    dostaje najmniejszy konieczny łuk do wnętrza bramki, nawet gdy umiejętność
    strzelca nie wygenerowała własnego dużego podkręcenia. Wynik, szanse i
    deterministyczny cel nie zmieniają się.

Boczne osłony siatki nie zostawiają szczeliny
---------------------------------------------
30.07.2026, 11:36

  Poprawki:
  • Fizyczna osłona bocznej siatki obejmuje teraz cały trapez wolnostojącej
    bramki, także przy głębszej dolnej ramie. Poprzednie wyśrodkowanie
    prostokątnego zabezpieczenia zostawiało trójkątną szczelinę przy
    narożniku; piłka mogła przez nią przejść po strzale z boku. Osłona ma też
    większą grubość, dzięki czemu ciągła kolizja piłki pewnie ją wykrywa.

Kolejne wślizgi nie powtarzają tej samej blizny
-----------------------------------------------
30.07.2026, 11:20

  • Losowanie głównego śladu po wślizgu pamięta poprzednio użyty materiał.
    Jeżeli bieżąca pula zawiera co najmniej dwa warianty, następny wybór jest
    równomiernie losowany spośród wszystkich pozostałych, więc dwie identyczne
    blizny nie pojawiają się bezpośrednio po sobie.
  • Zasada działa osobno dla pięciu zwykłych blizn, dwóch śladów „keczupu” po
    utracie piłki oraz puli dodatkowych rozprysków po wślizgu od tyłu. Pula z
    jednym wariantem powtarza go jako jedyną możliwą opcję.
  • Losowanie pozostaje wyłącznie kosmetyczne i nadal korzysta z wizualnego
    generatora Unity, bez wpływu na deterministyczne rozstrzygnięcie odbioru.

Animacje bramkarza i wspólne wślizgi
------------------------------------
30.07.2026, 11:19

  • Bramkarz przechodzi w jeden z dwóch klipów gotowości, gdy rywal prowadzi
    piłkę na jego połowie; wariant jest stały dla drużyny, a stan pozostaje
    wyłącznie prezentacją bez wpływu na reguły meczu.
  • Parady korzystają z dwóch osobnych klipów zależnie od strony strzału, a
    wykop z ręki odtwarza gotowy GoalkeeperDropKick.
  • Bramkarz niosący piłkę z pola karnego na zewnątrz odkłada ją na murawę
    jednym z dwóch klipów GoalkeeperPlacingBall; animacja i zejście piłki z
    rękawic do stopy działają tak samo dla gracza, komputera i gościa
    sieciowego.
  • Wślizg z boku, po skosie i od tyłu korzysta odpowiednio z SoccerTackle,
    SoccerTackle2 i SoccerTackle3 u każdego zawodnika, łącznie z bramkarzem;
    frontalny odbiór na stojąco zachowuje własną animację.
  • Wspólny StandingUp kończy wślizg, paradę i przewrócenie niezależnie od
    roli zawodnika oraz strony upadku.
  • Jedenaście osobnych FBX-ów Mixamo jest importowanych jako klipy Humanoid,
    śledzonych przez sygnaturę generatora prefabów i sprawdzanych testem
    assetów dla obu modeli zawodnika.
  • Dokumentacja inwentaryzuje klipy FBX oraz nadal aktywne animacje
    proceduralne. UUID klienta został podbity ze względu na zmianę animacji i
    czasu prezentacji wspólnych akcji sieciowych.

Czysty strzał w okienko
-----------------------
30.07.2026, 10:41

  • Gol automatycznie kierowany w górny narożnik leci dokładnie w przestrzeń
    „top bins”: środek piłki mija słupek i poprzeczkę o 0,36 jednostki,
    pozostawiając od obu rur widoczny prześwit po uwzględnieniu promienia
    piłki.
  • Górny narożnik zawsze ma bezpośredni wariant gola i nie może zostać
    zamieniony w trafienie od słupka ani poprzeczki. Losowy gol od słupka
    pozostaje dostępny dla niskich strzałów w skrajne pola; szansa zdobycia
    bramki nie zmienia się.
  • Test regresji wymusza stuprocentowe szanse obu wariantów obramowania i
    potwierdza, że rozstrzygnięty gol w okienko nadal pozostaje bezpośredni.
  • UUID klienta został podbity, ponieważ zmienił się deterministyczny podtyp
    i tor górnego gola.

Log meczu wyjaśnia tor każdego strzału
--------------------------------------
30.07.2026, 10:24

  • Tekstowy log meczu zapisuje przy strzale pole początkowe i cel, rodzaj
    pudła wraz ze stroną oraz kierunkiem odbicia albo rodzaj gola od
    obramowania.
  • Każdy strzał dostaje osobny wpis diagnostyczny TOR: wybrany wariant
    animacji, decyzję o paradzie, logiczne i widoczne pole bramkarza,
    początkową pozycję piłki, cel w świetle bramki, cel końcowy, początkowy
    punkt rękawic oraz parametry krzywej.
  • Format logu meczu został podbity do wersji 2; wartości świata mają zapis
    niezależny od ustawień językowych systemu.

Większy, szeroki kleks po wślizgu od tyłu
-----------------------------------------
30.07.2026, 09:42

  • Dodatkowy „keczup” po skutecznym wślizgu od tyłu nie wygląda już jak
    cienka pajęczyna smug. Tekstura przedstawia jeden szeroki, płaski i
    połączony kleks gęstego keczupu z nieregularnymi brzegami, grubym środkiem
    oraz krótkim ogonem po wyciśnięciu.
  • Nakładka na boisku wzrosła z 0,72 × 0,36 do 1,08 × 0,62 pola, dzięki czemu
    efekt pozostaje czytelny obok przewróconego zawodnika także w dalszym
    widoku kamery.

Krótszy komentarz na iPadzie
----------------------------
30.07.2026, 09:30

  • Każda składana wypowiedź komentatora ma teraz semantyczną granicę między
    bazowym opisem zdarzenia a opcjonalnymi dopowiedzeniami: reakcją na
    prawdopodobieństwo, smaczkiem zawodnika lub reprezentacji i pomiarem
    strzału.
  • Desktop nadal pokazuje pełną wypowiedź, natomiast tabletowy HUD wyświetla
    wyłącznie kompletny opis bazowy. Nie ucina tekstu według liczby znaków ani
    w środku zdania, dzięki czemu komentarz mieści się w niższym pasku na
    iPadzie.

Jasna zasada diagnostyki C#
---------------------------
30.07.2026, 09:08

  • Instrukcja projektu wymaga diagnostyki csharp-ls po każdej strukturalnej
    zmianie C#, w tym po zmianie sygnatur, parametrów, wywołań, nazw i
    zależności między klasami.
  • Zmiany ograniczone do literałów, formatowania lub danych nie wymagają
    diagnostyki językowej, o ile nie mogły naruszyć składni C#; nadal
    obowiązuje zakaz lokalnego budowania i uruchamiania testów Unity/C#.

Naturalne tory strzałów przy bramce
-----------------------------------
30.07.2026, 09:03

  • Zwykłe strzały, gole i loby celowane w skrajne pola zachowują widoczny
    prześwit od słupków; tylko wynik jawnie oznaczony jako słupek lub
    poprzeczka prowadzi piłkę do obramowania i odtwarza jego dźwięk.
  • Obroniony strzał płynnie śledzi poruszające się rękawice bramkarza na
    całej końcówce lotu, zamiast nagle przeliczać tor po zmianie pozy
    animacji.
  • UUID klienta został podbity, aby starsze wydania nie łączyły się w meczu
    sieciowym z klientem pokazującym inne tory piłki.

  Poprawki:
  • Piłka lecąca w światło bramki nie zmienia już gwałtownie kierunku tuż
    przed złapaniem lub odbiciem przez bramkarza.
  • Strzał bez rozstrzygniętego kontaktu z obramowaniem nie wygląda już jak
    bezdźwięczne trafienie w słupek.

Komentator mówi językiem boiska
-------------------------------
30.07.2026, 09:00

  Poprawki:
  • Komentarze końca ruchu nie używają już technicznych pojęć tury, rundy ani
    aktywacji. Zawodnik zamiast tego zatrzymuje się, zostaje na pozycji lub
    oddaje inicjatywę zgodnie z sytuacją na boisku.
  • Test regresji wielokrotnie losuje kwestie zawodnika z pola i bramkarza dla
    różnych stanów posiadania, pilnując, aby zakazane techniczne określenia
    nie wróciły do komentarza.

Uporządkowana struktura katalogów z assetami i Unity 6000.5.6f1
---------------------------------------------------------------
30.07.2026, 08:33

  • Projekt jest podbity do Unity 6000.5.6f1 wraz z pakietami Collaborate
    2.13.3 i Input System 1.20.0.
  • Assets/ ma ustaloną, opisaną strukturę: źródłowa grafika, której gra nie
    ładuje po ścieżce, leży w Assets/Art/, a Assets/Resources/ zawiera
    wyłącznie to, co kod wczytuje przez Resources.Load. Źródłowe FBX-y postaci
    przeniesiono z Assets/Models/ do Assets/Art/Models/, więc nie trafiają już
    do paczki jako zasób runtime'owy.
  • Resources/Audio/ jest rozdzielone na Anthems/ z motywami reprezentacji,
    Music/ z motywem menu i meczu oraz Sfx/ z efektami.
  • Resources/Textures/ jest rozdzielone na Kits/, Pitch/, Materials/, VFX/ i
    Board/. Nakładki rysowane na boisku przestały leżeć w podkatalogu UI/
    wewnątrz tekstur 3D, a grafika interfejsu ma własny kubełek
    Resources/UI/Widgets/.
  • Natywne pliki .mm dla platform Apple leżą w Assets/Plugins/Apple/; ich
    ustawienia importu nadal jawnie wskazują iOS i tvOS, więc żadna platforma
    nie jest wybierana po nazwie katalogu.
  • Opisy etapów projektu przeniesiono z Assets/ do .ai/stages/, bo nie są
    assetami gry.
  • .ai/PROJECT-INSTRUCTIONS.md opisuje docelową strukturę wraz z regułami
    obowiązującymi agentów: co wolno trzymać w Resources/, jak dzielić
    tekstury 3D od interfejsu, konwencję nazw, obowiązek przenoszenia plików
    .meta razem z assetem i zakaz zostawiania plików luzem w korzeniu Assets/.
  • Z Resources/ wypadły assety, których nie ładuje żadna linia kodu ani żadne
    ustawienie projektu: 46 z 59 ikon pada DualSense, cztery flagi bez sufiksu
    rozdzielczości, po które loader nigdy nie sięgał (England, Italy, Spain,
    Fallback), oraz PitchGrass przy używanych wariantach Light, Medium i Dark.
    Paczka nie nosi już tych plików.
  • PlayerView nie ma już zaparkowanej ścieżki prezentacji HD-2D. Zawodnik
    jest budowany wyłącznie jako model 3D, więc z klasy zniknęła nieosiągalna
    metoda budująca billboard ze sprite'em, pola opisujące jego hierarchię
    oraz wszystkie warunki rozgałęziające animacje na wariant sprite'owy i
    model. Plik skurczył się o około 460 linii, a wraz z nim zniknęły dwie
    sylwetki HD-2D z Resources/Characters/.
  • Usunięto Assets/DefaultNetworkPrefabs.asset — pustą listę prefabów
    sieciowych generowaną przez pakiet Netcode for GameObjects, do której nic
    się nie odwoływało, bo NetworkManager powstaje w całości z kodu.

  Poprawki:
  • Z repozytorium usunięto resztki szablonu Unity (Assets/TutorialInfo/,
    Assets/Readme.asset), scenę odzyskaną po awarii edytora
    (Assets/_Recovery/0.unity), pusty katalog Assets/Shaders/ oraz zapisany w
    historii plik .DS_Store.

Komentarz rozpoznaje ruch i pozycję bramkarza
---------------------------------------------
29.07.2026, 20:25

  • Komentarz ruchu bramkarza rozróżnia wyjście od linii, powrót na linię,
    cofnięcie bliżej bramki, wysunięcie, przesunięcie w lewo lub w prawo,
    przekroczenie granicy własnego pola karnego oraz powrót do szesnastki.
  • Wysunięcie bramkarza o co najmniej dwa pola w jednej akcji jest traktowane
    jako agresywne skrócenie kąta i zawsze wywołuje ostrzeżenie o wystawieniu
    się na loba; zwykła korekta o jedno pole zachowuje spokojniejszy
    komentarz.
  • Wyjście bramkarza poza pole karne jest oceniane na podstawie przebiegu
    akcji: pogoń za wolną piłką, wyprowadzenie jej nogami, wysokie ustawienie
    za dominującym zespołem i ryzykowna wycieczka przy posiadaniu rywala mają
    osobne, emocjonalne pule. Dominacja nie jest zgadywana z samego posiadania
    — wymaga piłki w ostatniej tercji.
  • Zebranie luźnej piłki przez bramkarza otrzymuje osobny opis zależny od
    tego, czy interwencja kończy się wewnątrz pola karnego, po powrocie do
    niego, czy daleko za szesnastką.

  Poprawki:
  • Koniec aktywacji bramkarza nie jest już bezwarunkowo opisywany jako
    pozostanie na linii. Komentarz sprawdza jego faktyczne pole i rozróżnia
    linię bramkową, wysuniętą pozycję w szesnastce oraz rolę ostatniego
    obrońcy poza polem karnym.
  • Kontekstowe komentarze bramkarza nie dostają losowego dopisku, który
    mógłby zaprzeczyć właśnie opisanemu ruchowi albo położeniu.

Dźwięk piłki odbijającej się od głowy
-------------------------------------
29.07.2026, 20:14

  • Nieudane przyjęcie dalekiego wykopu bramkarza odtwarza osobny efekt boing
    dokładnie w klatce, w której piłka dotyka głowy zawodnika i rozpoczyna
    odbicie.
  • Efekt został zapisany jako jednogłosowy Ogg Vorbis 44,1 kHz zamiast
    nieskompresowanego stereofonicznego WAV, zmniejszając rozmiar z około 388
    KB do 20 KB.

Siedem blizn i mocniejszy ślad wślizgu od tyłu
----------------------------------------------
29.07.2026, 19:54

  • Pula trwałych śladów po wślizgach wzrosła z trzech do siedmiu wariantów:
    doszły trzy bliskie wyrwy, cienka esowata bruzda oraz dwa rozdarcia z
    bardzo drobnymi czerwonymi śladami „keczupu”.
  • Nieskuteczny wślizg losuje jeden z pięciu zwykłych śladów darni. Czerwony
    wariant pojawia się wyłącznie po wślizgu, w którym zawodnik z piłką
    stracił ją przez czyste przejęcie albo wybicie.
  • Oba czerwone warianty mają „keczup” wyłącznie na dodatnim końcu tekstury.
    Przy takim śladzie losowe odchylenie jest wyłączone, a jego dodatnia oś
    biegnie dokładnie od odbierającego do zawodnika, który stracił piłkę.
  • Skuteczny wślizg od tyłu, który przewraca prowadzącego piłkę, dokłada
    bliżej niego drugą warstwę z większym rozpryskiem „keczupu”. Warstwa nie
    zawiera darni, więc wzmacnia czerwony efekt bez dublowania blizny murawy.
  • Warstwa blizn automatycznie ładuje wszystkie tekstury ze swojego katalogu
    zasobów, rozpoznaje zwykłe czerwone warianty po nazwie Ketchup, a
    dodatkowy rozprysk od tyłu po nazwie KetchupExtra.

Większe zakładki statystyk, równe menu meczu i gest zoomu
---------------------------------------------------------
29.07.2026, 15:53

  • Blok statystyk sieciowych jest szerszy: przyciski LOKALNE i SIECIOWE mają
    po 400 jednostek zamiast 260 i większy napis, a pięć zakładek pod nimi
    dzieli dokładnie tę samą szerokość, więc STRZELCY czy HISTORIA mieszczą
    się w swoim polu również na tablecie, gdzie każdy napis jest o rozmiar
    większy. Cała geometria nadal wynika z dwóch stałych opisujących rząd
    zakładek zakresu.
  • Rozwinięte menu meczu ma dokładnie szerokość przycisku MENU, który je
    otwiera — także w układzie dotykowym, gdzie przycisk jest szerszy.
    Wszystkie miary wewnątrz panelu (kolumny kamery, linie przy podpisie,
    przyciski na całą szerokość) liczą się od tej jednej wartości, więc panel
    i przycisk czytają się jak jedna płyta.
  • Na ekranie dotykowym zoom kamery jest gestem: dwa palce zmieniające
    odległość o piątą część krótszego boku ekranu przesuwają kamerę o jeden
    stopień drabinki zoomu, a kolejny taki ruch o następny. Dopóki na ekranie
    są dwa palce, gest jednym palcem jest porzucany, więc szczypnięcie nigdy
    nie kończy się wyborem zawodnika.
  • Schemat sterowania dotykowego w opcjach opisuje wyłącznie dotyk: zoom
    pokazuje SZCZYPNIJ zamiast klawiszy − i +, a ZAKOŃCZ oraz MENU mówią
    wprost, że są przyciskami na ekranie meczu.

Czytelniejsze napisy na tabletach
---------------------------------
29.07.2026, 11:29

  • Na tablecie (duży, mało panoramiczny ekran, ten sam warunek co dla
    większych pól dotyku) każdy napis interfejsu jest tworzony w powiększonym
    rozmiarze. Powiększenie jest największe dla najdrobniejszych napisów —
    tabel, opisów i podpisów — i wygasa całkowicie przy rozmiarze 28, więc
    nagłówki i tytuły zostają takie jak dotąd i nie rozpychają układu.
  • Rozmiar liczy jedna funkcja UiSupport.ScaledFontSize, przez którą
    przechodzi cała fabryka napisów, więc żaden ekran nie musi znać reguły z
    osobna. Komentarz meczowy, który sam dobiera rozmiar do długości zdania,
    przelicza go tą samą funkcją.

Czytelniejsze nagłówki wpisów w changelogu dla graczy
-----------------------------------------------------
29.07.2026, 11:22

  • Na stronie POBIERZ tytuł każdego wpisu „Co nowego” jest wyraźnie większy,
    a jego data biała i większa zamiast przygaszonej drobnej — dzień wydania
    widać teraz bez wpatrywania się w ekran.

Rekordy bramek: najdalsza, najsilniejsza i najszybsza
-----------------------------------------------------
29.07.2026, 11:16

  • Tabela rekordów — w grze i na stronie — ma trzy nowe pozycje liczone
    wyłącznie z goli, a nie z celnych strzałów: NAJDALSZY GOL, NAJSILNIEJSZY
    GOL i NAJSZYBCIEJ ZDOBYTY GOL. Dotychczasowe rekordy strzałów zostają obok
    nich, bo strzał obroniony przez bramkarza to nie to samo osiągnięcie co
    gol.
  • Statystyki meczu zapisują przy każdej zdobytej bramce jej dystans,
    prędkość i czas meczu, w jakim padła. Najszybszy gol jest jedynym
    rekordem, w którym wygrywa mniejsza wartość, i jest pokazywany jako mm:ss;
    przy remisie wartości rekord zostaje przy meczu, w którym padł wcześniej.
  • Raport meczu przesyła nowe rekordy do serwera, a baza dostała na nie
    kolumny dodawane migracją, więc istniejące mecze pozostają nietknięte i po
    prostu nie mają tych rekordów. Lokalna tabela rekordów na urządzeniu liczy
    je z zapisanych raportów tak samo jak serwer.
  • UUID protokołu serwera został podbity, bo raport meczu przekazuje teraz
    dodatkowe pola.

Wspólny nagłówek stron WWW i czytelniejsza typografia
-----------------------------------------------------
29.07.2026, 11:01

  • Tytuł serwisu, kafelki podsumowania z przewijanym paskiem ostatnich
    wyników oraz menu są jednym, współdzielonym blokiem: szablon site-header
    ze stylami i skryptem obok niego. Strona statystyk i szczegóły meczu
    wstawiają go tym samym wywołaniem, więc menu jest wszędzie pełne i
    identyczne, a pasek ostatnich wyników pokazuje się także na stronie meczu.
  • Lista zakładek ma jedno źródło po stronie serwera (siteTabs), z którego
    korzysta zarówno menu, jak i rozpoznawanie adresu /stats/{zakładka}. Na
    stronie meczu podświetlona zostaje zakładka ostatnich spotkań.
  • Zakładka rankingu ELO nazywa się teraz „RANKING”.
  • Kolumna z numerem miejsca ma tę samą szerokość w każdej tabeli, strona
    zawsze rezerwuje miejsce na pasek przewijania, a objaśnienie zmian
    tygodniowych stoi pod tabelą rankingu — przez to przełączanie zakładek nie
    przesuwa już treści w bok ani w dół.
  • Strony czytają się z większej odległości: podniesiony bazowy rozmiar
    tekstu, tytuł, nagłówki paneli, nagłówki tabel i liczby w kafelkach, a
    data pierwszego meczu jest biała i większa zamiast złotej i drobnej.

Statyczna analiza C# dostępna przez csharp-ls
---------------------------------------------
29.07.2026, 08:38

  • Instrukcje projektu dopuszczają używanie zainstalowanego csharp-ls do
    nawigacji po symbolach, wyszukiwania referencji i diagnostyki statycznej,
    nadal zabraniając lokalnego budowania, uruchamiania i testowania kodu C#
    oraz Go.

Każdy gracz ogląda mecz ze swojej strony
----------------------------------------
29.07.2026, 08:14

  • W meczu sieciowym kamera gospodarza zaczyna pod kątem 45°, a kamera gościa
    po przeciwnej stronie pod kątem 225°, dzięki czemu lokalna drużyna jest
    dla każdego gracza stroną bliższą. Sekwencja wejścia wykonuje pełny obrót
    od lokalnego kąta i wraca dokładnie do niego przed pierwszym gwizdkiem.
  • Lokalna orientacja pozostaje bazą po zmianie widoku i po ręcznych obrotach
    kamery, natomiast sterowanie izometryczne nadal interpretuje górę jako
    kierunek ataku bieżącego gracza.
  • Host i gość wyprowadzają wzór koszenia murawy z autorytatywnego seedu
    meczu, więc renderują identyczne boisko bez zużywania deterministycznego
    generatora rozgrywki. Mecze lokalne nadal losują murawę niezależnie.
  • UUID klienta został podbity, ponieważ zmieniła się animacja wejścia i
    bazowa orientacja kamery w meczu sieciowym.

Wykres pingu wykorzystuje całą szerokość panelu
-----------------------------------------------
29.07.2026, 07:50

  • Z panelu meczu online usunięto zbędny napis POŁĄCZONO; zerwane połączenie
    nadal prowadzi bezpośrednio do istniejącego ekranu przerwania meczu.
  • Wykres historii pingu rozciąga się od lewego do prawego marginesu panelu,
    a aktualna wartość jest wyśrodkowana na wykresie białym, pogrubionym
    tekstem z kontrastowym obrysem.

Ostatnie ujęcie powtórki wraca prosto do historii
-------------------------------------------------
29.07.2026, 07:41

  Poprawki:
  • Po ostatnim ujęciu top-down powtórki uruchomionej z historii gra od razu
    wraca do historii meczu. Nie zwalnia już reakcji po golu, nie
    synchronizuje odtworzonego stanu na planszę i nie pokazuje powrotu
    zawodników do pozycji wyjściowych przed zamknięciem replayu.
  • UUID klienta został podbity, ponieważ końcowy przebieg animacji zapisanej
    powtórki zmienił się dla obu uczestników meczu sieciowego.

Kompaktowy układ informacji o meczu online
------------------------------------------
28.07.2026, 20:14

  • Panel meczu online układa informacje w naturalnej kolejności: runda
    zajmuje pierwszy wiersz, Ruch: pseudonim drugi, a stan połączenia, wykres
    historii i ping trzeci.
  • Szerokość panelu nie ma już stałego minimum; jest przeliczana na podstawie
    najszerszego aktualnego wiersza i zachowuje równy margines po obu stronach
    także po zmianie tury albo wartości pingu.
  • Wysokość panelu została zmniejszona ze 108 do 84 jednostek, a trzy wiersze
    mają zwarty, równy rytm pionowy i niewielki margines dolny.
  • Ping jest mierzony natychmiast po pokazaniu panelu, a następnie co 5
    sekund przez nową, bezpośrednią wymianę pakietów ping–pong między
    graczami. HUD pokazuje czas powrotu świeżego pakietu zamiast wielokrotnie
    odczytywać tę samą pasywną próbkę transportu.
  • Czteropunktowy wskaźnik jakości został zastąpiony pozbawionym osi wykresem
    ostatnich 12 pomiarów. Linia przesuwa się po każdej świeżej próbce, używa
    schodkowych połączeń inspirowanych asciigraph i zmienia kolor wraz z
    aktualnym opóźnieniem.
  • UUID klienta został podbity, ponieważ obie strony meczu muszą obsługiwać
    nowe komunikaty pomiaru opóźnienia.

Drużyna gospodarza widoczna na liście pokojów
---------------------------------------------
28.07.2026, 19:57

  • Lista dostępnych pokojów ma osobną kolumnę z reprezentacją wybraną przez
    gospodarza. Nazwa drużyny korzysta z Handel Gothic i koloru jej stroju, a
    nieprawidłowa wartość ze starszych danych jest pokazywana jako neutralna
    kreska.
  • Kolumny pokoju i gospodarza są proporcjonalnie zwężone, dzięki czemu nowa
    informacja mieści się bez zmniejszania statusu ani przycisku dołączenia;
    pseudonim gospodarza również używa Handel Gothic.

Czytelny panel rundy i status meczu online
------------------------------------------
28.07.2026, 19:40

  • Panel rundy wyznacza szerokość z faktycznej długości treści, zachowuje
    jednakowy margines po obu stronach i składa metadane meczu z osobnej nazwy
    drużyny zapisanej krojem Handel Gothic.
  • W meczu sieciowym wyrównany do lewej stan POŁĄCZONO lub ROZŁĄCZONO
    sąsiaduje z pingiem bezpośredniego transportu gry i czterostopniowym
    wykresem z rosnących kropek, którego kolor oraz wypełnienie odpowiadają
    jakości łącza.
  • Dolny wiersz ma prostą postać Ruch: pseudonim; nazwa właściwego gracza
    pozostaje zapisana w Handel Gothic i kolorze jego drużyny.
  • Wskaźnik powtórki na czas odtwarzania zastępuje wszystkie elementy
    kontekstu meczu, po czym przywraca kompletny układ rundy i sieci bez
    nakładania tekstów.

Napięta siatka ugina się pod uderzeniem piłki
---------------------------------------------
28.07.2026, 17:59

  • Geometria bramki korzysta bezpośrednio z ramy wyodrębnionej z
    dostarczonego modelu Goal_Net, z jego gładkimi narożnikami, okrągłymi
    słupkami i zintegrowanymi wspornikami, zamiast odtwarzać ją z
    przecinających się cylindrów. Model jest normalizowany do regulaminowego
    światła 7,32 × 2,44 m i głębokości 1,70 m, a jego punkt zaczepienia leży
    dokładnie na linii bramkowej. Zielony apron i porcelanowa obudowa są
    wydłużone wyłącznie za liniami bramkowymi: zapas rośnie z 1,0 do 1,5
    jednostki na końcu, pozostawiając całą ramę na blacie bez poszerzania
    boków.
  • Dach, tył i boki siatki są ciągłymi, proceduralnie dzielonymi panelami
    sprężynowymi. Krawędzie pozostają zakotwiczone, lokalny impuls rozchodzi
    się na sąsiadów, a tłumienie przywraca powierzchnię do ramy; środkowy pas
    reprezentacji jest osobnym materiałem w tej samej geometrii, więc nie
    tworzy sztywnego szwu.
  • Kolorowy pas siatki nigdy nie przyjmuje bieli z podstawowego stroju.
    Bardzo jasne reprezentacje używają narodowego koloru wykończenia (Anglia i
    Polska czerwieni, Argentyna błękitu), a końcowe zabezpieczenie zastępuje
    każdą nadal zbyt jasną wartość ciemnym granatem.
  • Fizyczna powierzchnia kolizji pozostaje prosta, nieruchoma i niezależna od
    wizualnej deformacji. Dzięki temu ugięcie nie wpływa na zaliczenie gola
    ani zabezpieczenia piłki, a panel otrzymuje rzeczywisty punkt, kierunek i
    prędkość pierwszego kontaktu.
  • Pierwszy kontakt z siatką jest zapisywany razem z ujęciem gola. Oba kąty
    powtórki resetują panel, odtwarzają impuls we właściwej chwili i prowadzą
    sprężynę w tym samym tempie 0,5× co nagraną fizykę piłki.
  • UUID klienta został podbity, ponieważ zmieniła się geometria i animacja
    bramki.

  Poprawki:
  • Rama GoalFrame.fbx jest ustawiana pionowo z zachowanego układu osi Z-up, a
    jej ukryta centymetrowa skala importu 0,01 jest kompensowana jednolitą,
    sprawdzoną w scenie skalą 80. Zachowuje to oryginalne proporcje modelu bez
    rozciągania poszczególnych osi. Lustrzany offset 0,14 jednostki uwzględnia
    pivot leżący na zewnętrznej powierzchni rury: słupek zaczyna się razem z
    linią boiska, poprzeczka pokrywa się z osią linii bramkowej, a obie ramy
    zachowują identyczne ustawienie. Wizualne panele siatki są lustrzanie
    wsunięte o 0,07 jednostki w przekrój ramy, dzięki czemu włókna kończą się
    wewnątrz słupka i nie prześwitują przez jego przednią powierzchnię;
    fizyczne zabezpieczenia pozostają na logicznej płaszczyźnie bramki.

iPad nie przyciemnia ekranu podczas gry
---------------------------------------
28.07.2026, 17:32

  Poprawki:
  • Gra utrzymuje ekran urządzenia mobilnego aktywny także podczas długich
    animacji i sterowania kontrolerem, a po powrocie z tła ponownie ustawia
    blokadę systemowego usypiania.

Powtórka ma właściwą muzykę i dźwięk obramowania
------------------------------------------------
28.07.2026, 17:27

  Poprawki:
  • Odtwarzanie zapisanych bramek nie uruchamia już motywu głównego meczu ani
    nie czeka na późniejsze przejście muzyczne. Tryb powtórki od razu buduje
    źródła audio z utworem reprezentacji gospodarza; jeżeli ta reprezentacja
    nie ma własnego nagrania, powtórka pozostaje bez muzyki.
  • Każde ujęcie gola od słupka albo poprzeczki odtwarza dźwięk obramowania
    dokładnie wtedy, gdy deterministyczny tor dociera do punktu kontaktu.
    Reżyser powtórki korzysta z tego samego źródła efektów co prezentacja
    strzału na żywo.
  • Zwykły mecz zachowuje dotychczasowy przebieg: motyw główny towarzyszy
    prezentacji, a po pierwszym gwizdku płynnie przechodzi w muzykę lokalnej
    reprezentacji.

Lob domyślnie celuje w najlepsze pole
-------------------------------------
28.07.2026, 16:35

  • Wejście w akcję LOB od razu wybiera legalne pole bramki z najwyższą
    wyliczoną szansą na gola, tak samo jak zwykły strzał. Automatyczny wybór
    pokazuje obrys celu, tor lotu, pojedynek, procent i aktywny przycisk
    potwierdzenia.
  • Przy identycznej szansie lob wybiera pole bliższe środkowi bramki, a
    dalszy remis rozstrzyga stała kolejność pól na linii.

Wślizgi zostawiają trwałe blizny na murawie
-------------------------------------------
28.07.2026, 16:19

  • Każdy odbiór animowany jako wślizg dokłada na murawie jeden z trzech
    losowych śladów wyrwanej darni, dopasowany kierunkiem i rozmiarem do
    podejścia zawodnika. Zwykły odbiór z przodu nie zostawia śladu.
  • Blizny korzystają wyłącznie z wizualnego generatora losowego, nie wpływają
    na deterministyczny wynik akcji i pozostają na osobnej warstwie boiska aż
    do końca meczu.

Powtórka ucina długie toczenie po golu
--------------------------------------
28.07.2026, 16:18

  • Każde ujęcie powtórki ma twardy budżet 2 sekund od pełnego przekroczenia
    linii bramkowej. Budżet obejmuje zarówno nagraną fizykę piłki, jak i
    końcowe zatrzymanie obrazu.
  • Fizyczny odcinek nadal jest odtwarzany w tempie 50%. Gdy zapis odbijania
    albo toczenia jest dłuższy, powtórka kończy ujęcie po 2 sekundach zamiast
    przyspieszać zapis lub czekać na pełne zatrzymanie piłki.
  • UUID klienta został podbity, ponieważ zmienił się czas animacji powtórki.

Rzadkie gole wpadają od słupka i poprzeczki
-------------------------------------------
28.07.2026, 15:57

  • Po przejściu celności, bloku i bramkarza zwykły strzał otrzymuje
    deterministyczny podtyp gola. Trafienie celowane w jedną z dwóch skrajnych
    kratek ma 8% szansy wśród już zdobytych bramek wejść od słupka; szansa nie
    zależy od umiejętności strzelca.
  • Napastnik z umiejętnością strzału powyżej 0,80 automatycznie kieruje długi
    strzał w skrajną kratkę ku górnemu rogowi. Taki już zdobyty gol ma
    dodatkowe 6% szansy wejść od poprzeczki. Jeden wspólny rzut sprawdza
    najpierw słupek, potem poprzeczkę, więc warianty pozostają rzadkie i nigdy
    nie zwiększają bazowej szansy na gola.
  • Rdzeń zapisuje wariant Direct, Post albo Crossbar. Gra i powtórka używają
    tej samej deterministycznej funkcji toru przez rzeczywisty punkt
    obramowania; gra odtwarza dźwięk kontaktu, gol jest zgłaszany po pełnym
    przekroczeniu linii, a piłka od obramowania przed przejściem pod lokalną
    fizykę dociera jeszcze w bezpieczne miejsce wewnątrz siatki.
  • Komentator ma osobne, jednoznaczne pule kwestii dla gola od słupka i gola
    od poprzeczki; specjalna kwestia ma pierwszeństwo nawet wtedy, gdy
    bramkarz wykonywał paradę.
  • UUID klienta został podbity, ponieważ zmieniła się mechanika rozstrzygania
    i animacja strzału.

  Poprawki:
  • Gol od słupka był odgwizdywany prawidłowo przy pełnym przekroczeniu linii,
    ale piłka przechodziła pod fizykę dokładnie na tej granicy i siatka mogła
    natychmiast wyrzucić ją na boisko. Gole od słupka i poprzeczki nadal są
    zaliczane dopiero, gdy cała kula przekroczy linię; także awaryjne
    zakończenie animacji nie może już wywołać gola bez spełnienia tego
    warunku. Deterministyczny tor trwa do głębokości 0,35 jednostki, tuż przed
    celem 0,36 jednostki za linią.
  • Po kontakcie z obramowaniem cel jest ściągany w 65% ku środkowi światła
    bramki. Zamiast prostej do skrajnego pola kwadratowa krzywa prowadzi piłkę
    najpierw do środka, a na końcu obraca wektor niemal prostopadle w głąb
    siatki, więc fizyka nie dostaje już bocznego kierunku wyrzucającego piłkę
    przed bramkę.
  • Masa piłki pozostaje realistyczna (0,43 kg), natomiast kontakt z
    obramowaniem przekazuje fizyce siatki 38% prędkości (nie więcej niż 5
    jednostek stołu/s) oraz 55% rotacji deterministycznego odbicia. Siatka ma
    zerową sprężystość, a pierwszy kontakt pozostawia 18% prędkości i 35%
    rotacji. Zabezpieczenie fizyki obejmuje też poziome granice stołu: piłka,
    która ominie collider, wraca do ostatniej bezpiecznej pozycji z wygaszoną
    prędkością.

Podsumowanie meczu nie dubluje dolnego wyniku
---------------------------------------------
28.07.2026, 15:49

  Poprawki:
  • Pełnoekranowy raport końcowy zawiera własny wynik, ale dolny pasek meczu
    pozostawał nad nim, ponieważ korzysta z osobnej, najwyższej warstwy
    renderowania potrzebnej podczas powtórek. Wejście do raportu jawnie ukrywa
    teraz pasek i zatrzymuje jego miganie.

Cała powtórka pokazuje piłkę w zwolnionym tempie
------------------------------------------------
28.07.2026, 15:44

  • Powtórka ponownie wylicza gładki, deterministyczny lot do linii bramkowej
    bezpośrednio z tej samej funkcji co gra. Dopiero od przekroczenia linii do
    pełnego zatrzymania wykorzystuje zapis pozycji i obrotu z lokalnej fizyki;
    oba ujęcia pokazują więc ten sam lot, odbicie od siatki i toczenie bez
    odtwarzania klatkowego odcinka, który już jest wyliczalny.
  • Rejestrator pomija identyczne próbki powstające pomiędzy stałymi krokami
    fizyki, zachowując osobno dokładny punkt przekazania na linii i końcową
    pozycję. Interpolacja nie odtwarza już rytmu „pauza–skok”, a geometryczny
    przebieg fizycznego odbicia pozostaje zgodny z akcją na żywo.
  • Do chwili, w której cała piłka przekroczy linię bramkową, lot pozostaje
    deterministyczną animacją wspólną dla obu klientów. Dokładnie w tej klatce
    piłka przechodzi pod lokalną fizykę z pełną prędkością i rotacją
    ostatniego kroku; od tego momentu nie wpływa już na wynik i może odbić się
    na boisko, potoczyć albo zostać w bramce.
  • Punkt końcowy deterministycznej części leży 0,18 jednostki za linią —
    wystarczająco, by piłka o promieniu 0,16 przekroczyła ją w całości, ale
    nadal przed tylnym panelem. Prędkość wygasza dopiero rzeczywisty kontakt z
    materiałem siatki.
  • Każdy panel siatki ma dwustronną osłonę kolizyjną o grubości 0,08
    jednostki zamiast samej bezgrubościowej powierzchni. Chroni to przed
    tunelowaniem szybkiej piłki przez dach, tył i boki bramki z obu kierunków.
  • Pod całą siatką znajduje się niewidoczna podłoga kolizyjna, która zachodzi
    o promień piłki pod linię bramkową i boczne panele. Uzupełnia murawę
    kończącą się na linii boiska, więc odbita piłka ma na czym wylądować także
    wewnątrz bramki.
  • Piłka pilnuje dodatkowo własnej integralności podczas lokalnej fizyki:
    zapamiętuje ostatnie bezpieczne położenie nad murawą, a po wykryciu
    pozycji pod światem albo wartości NaN/nieskończonej natychmiast wraca na
    tę pozycję z wygaszoną prędkością. Awaria collidera nie może już usunąć
    piłki ani skierować kamery powtórki w przepaść.
  • Po obronie bramkarza albo bloku piłka może efektownie odbić się i
    potoczyć, ale kończy animację dokładnie w deterministycznej kratce luźnej
    piłki wyliczonej wcześniej przez silnik meczu. Lokalna prezentacja nigdy
    nie wybiera jej położenia w stanie gry.
  • Zapisany odcinek prawdziwej fizyki za linią bramkową jest odtwarzany w
    stałym tempie 50%. Jego długość wynika z rzeczywistego czasu odbijania i
    toczenia piłki, a osobna krótka pauza na końcowym położeniu zaczyna się
    dopiero po pokazaniu całego toru.
  • Pasek wyniku ma warstwę renderowania wyższą niż powierzchnia powtórki, a
    dolna krawędź obrazu powtórki dostała dodatkowe 4 piksele odstępu. Pasek
    komentarza nadal jest ukrywany na cały czas powtórki.
  • UUID klienta został podbity, ponieważ zmieniła się animacja i fizyczna
    prezentacja piłki.

  Poprawki:
  • Tor piłki w meczu i w powtórce potrafił się różnić, ponieważ powtórka
    liczyła drugą trajektorię z parametrów strzału i nie znała fizycznego
    odbicia od siatki.
  • Po dotknięciu siatki piłka w powtórce była kierowana pionowo w dół po z
    góry ustalonym profilu, przez co traciła kierunek, prędkość i rotację
    widoczne w normalnej akcji.
  • Punkt końcowy strzału znajdował się przy wysokiej piłce za tylnym panelem
    siatki, a fizyka zaczynała się dopiero po tym przeskoku; bezgrubościowy
    collider mógł dodatkowo przepuścić szybko poruszającą się piłkę.
  • Powierzchnia CRT powtórki mogła nachodzić na górną krawędź paska wyniku i
    zasłaniać ją własną warstwą.
  • Odtwarzanie całego lotu z próbek zbieranych w rytmie renderowania i fizyki
    powodowało widoczne przycinanie piłki w powtórce, szczególnie przed linią
    bramkową.
  • Murawa i jej collider kończyły się na linii bramkowej, a siatka nie miała
    dna. Po prawidłowym odbiciu od tylnego panelu piłka mogła spaść pod świat,
    zniknąć z obrazu i ściągnąć za sobą kamerę powtórki.
  • Przy strzale odbitym przez bramkarza albo obrońcę widoczny model piłki
    kończył animację w punkcie kontaktu, chociaż zielone podświetlenie i stan
    meczu wskazywały już inną, deterministycznie wylosowaną kratkę. Odbicie ma
    teraz ciągły tor do tej samej kratki, a końcowa synchronizacja nadal
    wymusza jej środek.
  • Po golu strzelonym przez komputer dźwięk, wynik, komentarz i celebracja
    czekały nawet kilka sekund na pełne zatrzymanie piłki w siatce. Komputer
    używa teraz tego samego sygnału przekroczenia linii co gracz: gol jest
    ogłaszany natychmiast, gdy cała piłka znajdzie się za linią, a jej
    fizyczne odbicia trwają równolegle.
  • Fizyczne odbicie piłki od siatki było wciskane w stałe 0,55–0,70 sekundy
    ujęcia, więc przy dłuższym torze poruszała się w powtórce z normalną albo
    nawet zwiększoną prędkością, podczas gdy deterministyczny lot był wyraźnie
    zwolniony.

Strzał z narożnika wygina się w boisko zamiast lecieć przez boczną siatkę
-------------------------------------------------------------------------
28.07.2026, 14:10

  Poprawki:
  • Piłka uderzona sprzed samej linii końcowej leciała prosto do wskazanej
    kratki bramki, czyli wzdłuż linii bramkowej i przez boczną siatkę, mimo że
    padał gol. Złożyły się na to dwie rzeczy: strzał z odległości do 1,6
    kratki od linii bramkowej miał wyłączone wyginanie, a samo wyginanie było
    liczone wyłącznie na osi bocznej boiska, więc przy locie równoległym do
    linii bramkowej przesuwało piłkę wzdłuż jej własnego toru i nic nie
    dawało.
  • Łuk strzału jest teraz mierzony w poprzek toru lotu. Dla strzału granego w
    bramkę ta prostopadła jest osią boczną boiska i tor wygląda dokładnie jak
    dotąd; dla piłki granej wzdłuż linii bramkowej ta sama prostopadła
    prowadzi w głąb boiska, więc lot wychodzi w pole i wraca do bramki.
  • Strzał z bezpośredniego dystansu traci łuk tylko wtedy, gdy jest grany na
    wprost — do 1,5 kratki w bok. Dalej w bok, czyli z narożnika, piłka wygina
    się zawsze; przy takim uderzeniu ładny tor jest ważniejszy od zgodności z
    celowaniem.
  • Im dłuższy odcinek wzdłuż linii bramkowej ma do pokonania piłka, tym
    szerzej wychodzi w boisko — do 1,6 raza.
  • Przycinanie łuku do linii bocznych bierze pod uwagę tylko tę część
    wygięcia, która faktycznie leży na osi bocznej; reszta prowadzi w głąb
    boiska, gdzie nie ma czego przekroczyć.
  • Tor liczy jedna wspólna metoda, więc podgląd celowania, lot w meczu i
    powtórka bramki pokazują to samo.

Komputer nie mija już luźnej piłki, którą mógł przejąć
------------------------------------------------------
28.07.2026, 13:50

  Poprawki:
  • Zawodnik komputera potrafił zakończyć ruch o kratkę od luźnej piłki, mimo
    że miał ją w zasięgu. W systematycznym sprawdzeniu 228 układów zdarzało
    się to w 70% przypadków. Przyczyną było wprowadzone wcześniej mieszanie
    celu przy luźnej piłce: ocena mierzy odległość do punktu docelowego, a
    przy sile pogoni mniejszej od 1 kratka obok piłki leży bliżej tego punktu
    niż sama piłka.
  • Przejęcie osiągalnej luźnej piłki jest teraz rozstrzygane przed punktacją
    i jej nie podlega — posiadanie bije pozycję. Po zmianie 100% na obu
    poziomach trudności; poziom łatwy też jej podlega, bo stanie obok darmowej
    piłki wygląda na zepsutą grę, a nie na ustępstwo dla początkującego.
  • Ograniczenia bramkarza zostały wydzielone do jednej metody MayEnter
    używanej i przez nową regułę, i przez filtr kratek. Bramkarz bierze piłkę
    w polu karnym oraz o kratkę od niego, ale nie dwie — sprawdzone osobno.

Luźna piłka przestaje być wyścigiem całej drużyny
-------------------------------------------------
28.07.2026, 13:20

  Poprawki:
  • Po odbitym strzale każdy zawodnik z pola biegł po luźną piłkę najkrótszą
    drogą, więc na jednej kratce zbiegało się sześciu zawodników, a reszta
    boiska zostawała pusta. W odtworzonej sytuacji — piłka w narożniku pola
    karnego po strzale z dystansu — do piłki ruszali obaj obrońcy, obaj
    pomocnicy i obaj napastnicy.
  • Każda rola ma teraz strefę odpowiedzialności, a siła pogoni za luźną piłką
    zależy od tego, jak blisko tej strefy piłka leży. Przy t oznaczającym
    położenie piłki od własnej bramki (0) do bramki rywala (1): obrońca 1 − t,
    pomocnik 1 − |t − 0,5|, napastnik t; dwie pierwsze role nie schodzą
    poniżej 0,15. Cel ruchu leży na odcinku od domowej pozycji roli do piłki,
    w proporcji tej siły.
  • Pozycje domowe przy luźnej piłce: obrońca 2 kratki za krawędzią własnego
    pola karnego, pomocnik linia środkowa, napastnik jego zwykła stacja
    liczona z linii drużyny.
  • Napastnik przy luźnej piłce na własnej połowie sprawdza dodatkowo, czy
    rywal wprowadził do bronionej połowy więcej zawodników z pola, niż zostało
    w niej swoich. Jeżeli tak, wraca po zawodnika, nie po piłkę — bierze w
    krycie najwysuniętego rywala. To osobne kryterium od liczenia ciał
    względem piłki, bo przy piłce pod samą linią końcową prawie nikt nie jest
    po stronie bramki względem niej i tamten rachunek nic nie mówi.
  • W odtworzonej sytuacji po zmianie po piłkę idą bramkarz i obrońca
    broniącej drużyny oraz napastnik atakującej, pomocnicy podchodzą
    częściowo, a obrońca drużyny atakującej zostaje z tyłu.

Napastnik komputera ustawia się pod drużynę, a nie pod piłkę
------------------------------------------------------------
28.07.2026, 12:45

  • Napastnik bez piłki nie wraca już odruchowo. Komputer liczy ciała po
    stronie bronionej bramki względem piłki: po swojej stronie zawodników z
    pola na wysokości piłki albo za nią plus bramkarza, po stronie rywala
    zawodników z pola na wysokości piłki albo przed nią razem z posiadaczem
    piłki. Pytający napastnik nie liczy się po żadnej stronie. Przewaga rywala
    oznacza powrót, jej brak — pozostanie wysoko i czekanie na kontrę. W
    pomiarze wypada to na 22–30% powrotów zamiast dotychczasowego automatu.
  • Stacja napastnika jest mierzona względem linii własnej drużyny, a nie
    względem piłki ani stałego punktu boiska: średnie wysunięcie kolegów z
    pola plus 4 kratki, gdy zostaje, albo plus 1,5, gdy jest potrzebny. Przy
    cofniętej drużynie schodzi razem z nią, przy wysokiej wychodzi wyżej.
    Odejście od osi to 0,5 + 0,5 × Width rozstawienia, więc drużyny grające
    szerokością wyraźniej schodzą do boku.
  • Stacja jest ograniczona z obu stron: nie głębiej niż kratkę od krawędzi
    własnego pola karnego i nie dalej niż do ostatniej tercji rywala. Trwanie
    w ostatniej fazie ataku, którego drużyna nie prowadzi, wyłącza napastnika
    z gry tak samo jak gonienie piłki do własnej szesnastki.
  • Napastnik zostawiony z przodu jest wyłączony z bloku obronnego — premia za
    doskok, linię podania i krycie jest dla niego zerowana. Bez tego ciągnęła
    go z powrotem do bloku i do własnego pola karnego.
  • Pomiar na 90 meczach: przebywanie w ostatniej tercji rywala spadło z 50%
    do 0%, odstęp od linii kolegów z +8,3 do +3,6…+4,0 kratki, a wejścia we
    własne pole karne wynoszą 2–5%, z czego 98% to sytuacje z niedoborem w
    obronie i piłką faktycznie w tym polu.

  Poprawki:
  • Napastnik w fazie ataku koczował na linii bramkowej rywala: cel jego ruchu
    to 4 kratki przed piłką, a przycięcie do planszy sadzało go na samej linii
    w 32% aktywacji bez piłki. Z linii światło bramki ma zerowy kąt (§8
    zasad), więc taki zawodnik nie zagrażał niczemu. Cel jest teraz przycinany
    tak, by zostawić 2 kratki od linii bramkowej — po zmianie 0–3%.

Piłka po golu przechodzi na prawdziwą fizykę
--------------------------------------------
28.07.2026, 11:40

  • Po przecięciu linii bramkowej piłka nie jest już prowadzona skryptem,
    tylko przekazywana silnikowi fizyki. Zachowuje kierunek i rotację
    uderzenia (22% prędkości i 70% rotacji z ostatniej klatki lotu), więc
    wpada w siatkę, wypada z niej wciąż kręcąc się zgodnie ze strzałem, może
    się potoczyć i zatrzymuje się tam, gdzie ją to zaniesie — zamiast tracić
    spin i spadać zawsze pionowo w dół.
  • Piłka ma Rigidbody i SphereCollider o masie i rozmiarach piłki meczowej,
    kinematyczne przez cały czas trwania animacji skryptowych. EnsureVisible,
    przez które przechodzi każdy ruch skryptowy, odbiera piłkę fizyce, więc
    silnik nigdy nie walczy z animacją.
  • Panele siatki dostały MeshCollider z materiałem fizycznym o znikomej
    sprężystości i dużym tarciu (siatka wygasza uderzenie, a nie odbija je jak
    trampolina). Collidery siatki są włączane wyłącznie na czas toczenia się
    piłki po golu, żeby nigdy nie przechwyciły kliknięcia w tarczę celowania w
    bramce; na ten sam czas wyłączane są collidery kolumn celowania, które
    stoją w świetle bramki.
  • Piłka wraca pod kontrolę skryptów, gdy się zatrzyma (albo po 2,6 s, gdyby
    nie chciała), więc powtórka i wznowienie gry zastają ją leżącą na murawie.
  • Rozstrzygnięcie meczu jest podjęte przez deterministyczny rdzeń na długo
    przed przekazaniem piłki fizyce, więc nic z tego nie może wpłynąć na
    wynik. Świadomie dopuszczamy, że dwaj gracze zobaczą piłkę w nieco innym
    miejscu — pozycja piłki i tak wraca ze stanu przy wznowieniu.
  • Piłka po golu nie miga już naprzemiennie i nie znika: miganie samej piłki
    (PlayGoalBlink) zostało usunięte razem z całą jego obsługą. Leży sobie w
    bramce do końca prezentacji gola i znika dopiero przy powrocie do widoku
    gry, gdy stan przekazuje ją drużynie rozpoczynającej. Znikło przy okazji
    rozjechanie się sygnałów: czas trwania animacji piłki należy teraz
    wyłącznie do jej ruchu, a nie do niezależnie odliczanego migania.

Bramkarz kryje kąt, a zawodnik może zostać przy piłce
-----------------------------------------------------
28.07.2026, 11:05

  • Bramkarz komputera nie kieruje się już do jednego stałego punktu przed
    bramką. Cel jego ruchu leży na prostej od środka własnej bramki do piłki,
    w odległości 1,8 kratki od linii bramkowej, więc przy akcji na skrzydle
    przesuwa się na tę stronę zamiast stać na środku i odsłaniać róg. W
    pomiarze na 30 meczach stoi zawsze dokładnie kratkę od własnej linii.
  • Luźna piłka we własnym polu karnym jest dla bramkarza bezwarunkowa: rusza
    po nią także wtedy, gdy stoi przy niej rywal. Wcześniej sąsiedztwo
    przeciwnika odbierało mu priorytet i potrafił zostać w bramce, patrząc na
    piłkę leżącą przed nim. Piłkę tuż poza polem karnym nadal traktuje jak
    decyzję o wyjściu i podejmuje ją tylko wtedy, gdy nikt z rywali nie stoi
    obok.
  • Ruch bramkarza omija warstwę wariacji i poziom trudności — zawsze bierze
    najlepszą kratkę. Jego podanie podlega im normalnie: wolno mu zagrać źle,
    nie wolno mu stać źle.
  • Aktywacja zawodnika z piłką nie musi kończyć się zagraniem. Przed wyborem
    podania komputer porównuje najlepsze z nich z wartością zatrzymania piłki
    (HoldScore), liczoną na tej samej skali: 0,45 × (BallControl − 0,25 ×
    liczba_kryjących) + 0,40 × 0,5 + 0,15 × swoboda − 0,12 × Directness. Człon
    postępu jest z definicji połowiczny, więc dobre podanie do przodu zawsze
    przebija zatrzymanie; wygrywa ono dopiero wtedy, gdy jedyne dostępne
    zagranie idzie w bok albo do tyłu, a zawodnik ma technikę i przestrzeń.
  • Porównanie dotyczy najlepszego podania, a nie tego wybranego przez warstwę
    wariacji, więc poziom łatwy nie zaczyna przez przypadek dusić piłki.
    Bramkarza nie dotyczy — on zawsze wyprowadza.
  • Pomiar na 30 meczach po 14 rund: komputer zostaje przy piłce w 14–15%
    aktywacji zawodnika z piłką, a najdłuższa seria takich decyzji pod rząd
    wynosi 1, więc gra się nie zatrzymuje.

Cała plansza mieści się w kadrze nad paskiem wyniku
---------------------------------------------------
28.07.2026, 11:05

  Poprawki:
  • Dolny róg planszy był ucinany przy krawędzi paska komentarza. Złożyły się
    na to dwie rzeczy. Po pierwsze kamera rezerwowała miejsce i na pasek
    wyniku, i na pasek komentarza (118 z 1080 pikseli), choć komentarz jest
    nakładką i może zasłaniać obraz — teraz rezerwowany jest wyłącznie pasek
    wyniku (72 z 1080), tak jak od dawna robi to kamera powtórki. Pasek wyniku
    nadal nigdy nie jest niczym zasłaniany.
  • Po drugie kadr był dobierany do samego boiska powiększonego o 15%, a na
    ekranie widać całą planszę: kremowy margines i wypukłą ramkę budowane
    przez TabletopEnvironment, sięgające około jednej komórki poza linię
    boczną. Przy krótszej osi ten zapas nie wystarczał i róg planszy wychodził
    poza kadr. ComputeOrthographicSize dopasowuje się teraz do planszy razem z
    obramowaniem, a zapas zszedł z 15% do 4%, bo nie musi już maskować braku.

Poziom trudności komputera w opcjach
------------------------------------
28.07.2026, 10:20

  • W opcjach pojawił się wybór poziomu trudności komputerowego rywala:
    NORMALNY (domyślny) albo ŁATWY. Wiersz TRUDNOŚĆ stoi w lewym panelu jako
    ostatni, pod siłą wibracji, i ma dwa przyciski obok siebie: zielony ŁATWY
    i pomarańczowy NORMALNY. Wybrany świeci swoją barwą, drugi jest wygaszony
    do ciemnego granatu, więc widać poziom bez czytania podpisu — opis obok
    wiersza okazał się zbędny. Cała kolumna panelu przesunęła się o jeden krok
    w górę, żeby nowy wiersz zmieścił się w ramce, a komunikat walidacji
    pseudonimu zszedł pod panele, bo zajmował miejsce potrzebne na ten wiersz.
    Tytuł panelu brzmi teraz PROFIL, DŹWIĘK I GRA. Ustawienie zapisuje
    DifficultyPreferences w PlayerPrefs, a MatchController odczytuje raz przy
    rozpoczęciu meczu, więc zmiana w trakcie nie przestawia rywala w połowie
    spotkania.
  • AiChoice.Pick przyjmuje poziom trudności. Na Easy zwraca zawsze ostatniego
    kandydata, czyli najsłabszą z zaoferowanych opcji. Kluczowe jest to, że
    wybiera źle wyłącznie spośród opcji, które funkcja oceny wcześniej
    zaakceptowała — nie łamie reguł i nie oddaje piłki za darmo.
  • Wybór podania i rogu bramki przechodzą teraz również przez AiChoice, a nie
    przez zwykłe maksimum. Bez tego poziom łatwy byłby ledwo odczuwalny, bo
    dotykałby wyłącznie ruchu i kolejności aktywacji. Na poziomie normalnym
    daje to dodatkową, zależną od umiejętności wariację podań i miejsca, w
    które leci piłka; kandydatami są odpowiednio podania w paśmie 0,08 oceny
    od najlepszego i komórki bramki w paśmie 0,06 szansy na gola.
  • Trudność nie dotyczy wyprowadzenia piłki przez bramkarza — tam nadal liczy
    się wyłącznie największa szansa powodzenia, bo rozdawanie prezentów spod
    własnej bramki wyglądałoby na błąd gry, a nie na ustawienie.
  • Tools/simulate-ai-match.py dostał przełącznik --difficulty easy|normal.
    Pomiar na 40 meczach po 12 rund, strona komputera: poziom łatwy zagrał 256
    podań zamiast 440, oddał 26 strzałów zamiast 96 i doskakiwał w 15% ruchów
    obronnych zamiast 50%. Średnia szansa podania wzrosła z 75,9% do 80,4%, bo
    najniżej oceniane podanie to zwykle bezpieczne zagranie do tyłu — taki
    rywal utrzymuje piłkę, ale nie robi z nią nic.
  • UUID klienta bez zmian: poziom trudności dotyczy wyłącznie meczu z
    komputerem, którego nie ma w trybie sieciowym.

Zróżnicowane ustawienie i krycie w obronie u komputera
------------------------------------------------------
28.07.2026, 09:40

  • Zawodnik komputera bez piłki nie biegnie już do niej. Cel ruchu zależy od
    roli i od tego, kto ma piłkę: przy własnym ataku obrońca trzyma się 4
    kratki za piłką, pomocnik oferuje się kratkę przed nią po przeciwnej
    stronie boiska, a napastnik wybiega 4 kratki do przodu; przy obronie
    obrońca cofa się na 35% drogi od piłki do własnej bramki, pomocnik
    doskakuje do rywala, a napastnik czeka 2 kratki za linią środkową na
    kontrę. Luźna piłka pozostaje wspólna — walczą o nią wszyscy.
  • Nowa klasa AiChoice w rdzeniu wybiera spośród kandydatów, którzy i tak
    wypadli blisko najlepszego: kratek oddalonych od celu o nie więcej niż 0,9
    kratki od najlepszej, maksymalnie czterech. Szansa trafienia w najlepszą
    to 0,55 + 0,42 × Q^1,3, gdzie Q liczy się z umiejętności istotnych dla
    danej decyzji. Zawodnik o Q = 0,9 wybiera optymalnie w 92% przypadków, o Q
    = 0,3 w 64%. Żadna wybierana opcja nie omija wcześniejszej oceny, więc
    jest to zróżnicowanie, a nie osłabienie AI.
  • W obronie komputer rozróżnia doskok od krycia. Każda rozważana kratka
    dostaje premię obronną: 18 za sąsiedztwo z posiadaczem piłki (pozwala od
    razu spróbować odbioru), 9 za stanięcie o kratkę od linii podania (czyni z
    zawodnika uprawnionego do przechwytu) i 6 za sąsiedztwo z potencjalnym
    odbiorcą. Premia za doskok dotyczy wyłącznie kratek faktycznie
    sąsiadujących z posiadaczem piłki, więc gdy zawodnik nie ma jak do niego
    dojść w tej aktywacji, sam z siebie wybiera odcięcie podania zamiast
    bezcelowego zbliżania się.
  • Aggression przechyla te wagi: premia za doskok rośnie o 1 + 0,40 ×
    Aggression, za krycie maleje o 1 − 0,40 × Aggression. W pomiarze Meksyk i
    Argentyna doskakują w 79% i 78% ruchów obronnych, Polska w 61%, Włochy w
    48%, a Szwajcaria w 51%. Linia albo zawodnik pilnowany już przez kolegę
    jest wart 25% premii, więc dwóch obrońców nie kryje tego samego. Cała
    premia jest ograniczona do 26 i nie dotyczy bramkarza.
  • Wybór aktywowanego zawodnika przechodzi przez tę samą warstwę: prowadzi
    najbliższy piłce, ale zawodnik oddalony o kratkę więcej też jest
    kandydatem, więc kolejność aktywacji w rundzie przestała być stała. Twarde
    priorytety — posiadacz piłki oraz bramkarz przy luźnej piłce w polu karnym
    — pozostają poza losowaniem.
  • Ziarno wariacji powstaje haszem z ziarna meczu, rodzaju decyzji,
    identyfikatora zawodnika, numeru rundy i pozycji, a nie z MatchState.Rng.
    Kości meczowe pozostają nietknięte, więc powtórki goli i ponowne symulacje
    odtwarzają te same decyzje.
  • Nowy Tools/simulate-ai-match.py odtwarza warstwę decyzyjną AI w Pythonie i
    mierzy jej schematyczność. Stałe BoardConfig, stałe strojeniowe ComputerAi
    oraz profile i style reprezentacji czyta wprost z plików C#, więc nie
    rozjeżdża się z kodem przy zmianie balansu. Przełącznik --baseline
    odtwarza zachowanie sprzed tej zmiany, --trace wypisuje przebieg meczu, a
    --random losuje ziarno osobno dla każdego meczu zamiast brać kolejne
    liczby od --seed. Domyślnie wynik jest powtarzalny, żeby dało się
    porównywać zmiany w AI; przy --random raport wypisuje użyte ziarna, więc
    zaskakujący przebieg da się odtworzyć przez --seed.
  • Pomiar na 12 meczach po 10 rund (Polska — Włochy): odsetek decyzji, w
    których wybrano opcję inną niż najwyżej oceniona, wzrósł z 0% do 18%. W
    ruchach obronnych doskok do posiadacza piłki spadł z 77% do 55%, stanięcie
    na linii podania wzrosło z 9% do 32%, a ruchy bez żadnego efektu obronnego
    spadły z 11% do 9%. Ten sam mecz z tym samym ziarnem nadal przebiega
    identycznie.
  • UUID klienta bez zmian: komputer gra wyłącznie offline
    (ComputerTurnRoutine nie startuje przy aktywnej sesji sieciowej), a
    warstwa wariacji nie tyka generatora meczu, więc dwaj klienci nie mają jak
    policzyć różnych wyników.

Rekordy wskazują mecz, rekordy całych spotkań i wspólny komponent wyniku
------------------------------------------------------------------------
28.07.2026, 07:46

  • Każdy rekord w zakładce REKORDY podaje datę oraz mecz z wynikiem, a
    komórka z meczem otwiera pełny raport tego spotkania — ten sam, który
    otwiera wynik w historii meczów. Działa w obu zakresach: lokalnym i
    sieciowym.
  • Rekordy lokalne wyliczane są z archiwum meczów tego urządzenia zamiast z
    osobnego zapisu w PlayerPrefs. Każdy zachowany raport niesie już rekordy
    swojego meczu, więc najlepszy z nich jest rekordem wszech czasów i od razu
    zna mecz, datę i wynik. Przy równych wartościach rekord zostaje przy
    meczu, który ustanowił go pierwszy — tak samo jak na serwerze.
  • GET /v1/stats/records zwraca dodatkowo datę meczu, nazwy obu stron i
    wynik, a strona statystyk pokazuje je jako kolumny DATA i MECZ, z
    odnośnikiem do strony meczu.
  • Doszły cztery rekordy samego meczu: najszybszy i najdłuższy mecz (czas
    trwania) oraz najmniej i najwięcej tur. Nikt ich nie ustanawia, więc
    kolumny zawodnika i reprezentacji zostają puste, a wartość czyta się
    według jednostki: czas jako mm:ss, liczba tur jako goła liczba, bo
    znaczenie niesie nazwa rekordu.
  • Rekordy meczu wyliczane są z kolumn duration_sec i rounds, w obie strony
    tego samego zapytania; przy równych wartościach rekord zostaje przy
    starszym meczu, tak jak przy rekordach zawodników.
  • Wynik meczu rysuje jeden wspólny komponent (web/match-result.html plus
    reguły .match-result i colorizeMatchResults()): dwa nicki w barwach swoich
    reprezentacji z wynikiem pomiędzy nimi, z odnośnikiem do raportu.
    Korzystają z niego historia spotkań, tabela rekordów i pasek ostatnich
    wyników, więc wynik nie może już wyglądać w trzech miejscach na trzy
    sposoby.
  • Historia spotkań renderuje swoje trzy komórki z tego samego komponentu, a
    nicki w rekordach są kolorowane dokładnie tak jak tam — z zamianą stroju
    gościa, kiedy oba komplety by się zlewały. recordRow przenosi w tym celu
    reprezentacje obu stron meczu, a nie tylko rekordzisty.
  • Lokalne rekordy całego meczu mają wreszcie właściciela: w kolumnie
    ZAWODNIK stoi nick z opcji (albo „Gracz”, jeśli nie ustawiono żadnego), a
    w REPREZENTACJI drużyna, którą ten mecz rozegrano. Archiwum lokalne
    zawiera wyłącznie mecze z komputerem, więc gospodarz jest zawsze
    człowiekiem siedzącym przy klawiaturze.
  • Ta sama zasada obowiązuje w statystykach sieciowych: rekord całego meczu
    jest przypisany gospodarzowi spotkania — jego nickowi i reprezentacji,
    którą grał. Gospodarz jest stroną raportującą mecz, więc lokalnie i
    sieciowo rekord należy do tego samego miejsca w raporcie. Widać to zarówno
    w grze, jak i na stronie statystyk.
  • Kolumna MECZ w grze pisze obie strony barwami kitów, z zamianą stroju
    gościa przy kolizji kolorów (NationalTeams.KitsForMatch), a wynik pomiędzy
    nimi na złoto. Komórka pozostaje klikalna, ale bez przebarwiania na
    najechanie — kolory stron są tam treścią, nie dekoracją.

Powtórka wypełnia przestrzeń nad wynikiem
-----------------------------------------
26.07.2026, 21:15

  Poprawki:
  • Kamera powtórki i ekran filtra CRT kończą się teraz bezpośrednio na pasku
    wyniku zamiast zachowywać pustą przestrzeń przeznaczoną dla ukrytego
    komentarza.
  • Pasek komentarza pozostaje niewidoczny przez cały czas powtórki i wraca
    dopiero po przekazaniu obrazu z powrotem do gry.

Obowiązek aktualizacji obu opisów mechaniki
-------------------------------------------
26.07.2026, 20:35

  • .ai/PROJECT-INSTRUCTIONS.md opisuje teraz oba dokumenty mechaniki obok
    siebie — .ai/GAMEPLAY-RULES.md dla agentów i docs/zasady-gry.html dla
    graczy — i nakłada obowiązek aktualizowania obu przy każdej zmianie
    reguły, wzoru, progu, kosztu akcji, zasięgu, szansy powodzenia, zachowania
    bramkarza, decyzji komputera, stylu reprezentacji, profili umiejętności
    albo warunków zakończenia meczu. Zadania nie można uznać za zakończone,
    dopóki oba pliki nie opisują stanu po zmianie.
  • Instrukcja rozdziela, co gdzie poprawić: w dokumencie dla agentów liczba,
    wzór i odnośnik do linii kodu, w stronie dla graczy zdanie, tabela, podpis
    pod rysunkiem oraz wartości zaszyte w skryptach rysujących wykresy, bo
    powtarzają one wzory z rdzenia i po zmianie balansu pokazywałyby
    nieprawdę. Zmiany czysto wewnętrzne, bez wpływu na liczby i zachowanie,
    nie wymagają ruszania żadnego z tych plików.
  • Instrukcja zastrzega, że strona dla graczy musi pozostać kompletnym
    dokumentem HTML z <!DOCTYPE html>, lang="pl" i <meta charset="utf-8"> oraz
    bez odwołań do zewnętrznych zasobów, bo gracz otwiera ją z rozpakowanego
    katalogu i bez tego trafia w tryb zgodności.
  • .ai/GAMEPLAY-RULES.md powtarza ten obowiązek w nagłówku i w liście zasad
    dla agenta zmieniającego mechanikę, żeby trafił do agenta również wtedy,
    gdy otworzy wyłącznie ten plik.

Zasady gry dla gracza dołączane do paczek
-----------------------------------------
26.07.2026, 20:10

  • Nowy docs/zasady-gry.html tłumaczy mechanikę meczu językiem gracza: turę i
    punkty akcji, rombowy zasięg ruchu, podanie z przechwytem, trzy etapy
    strzału, sześć warunków loba, cztery wyniki odbioru, odrębne reguły
    bramkarza, wznowienie po golu oraz style czternastu reprezentacji. Strona
    jest w całości samowystarczalna — bez zewnętrznych czcionek, skryptów i
    grafik — więc otwiera się z dysku bez internetu.
  • Zasięg ruchu na stronie jest interaktywny: kliknięcie kratki przestawia
    zawodnika i przerysowuje romb, a przełącznik pokazuje krótszy zasięg
    bramkarza i zakaz opuszczania własnej połowy. Dwie zajęte kratki wycinają
    w rombie dziurę, żeby widać było blokowanie przez zawodników.
  • Wykresy odtwarzają wzory z rdzenia: dwuczłonowy spadek szansy podania,
    rozkład przechwytu, podział czterech wyników odbioru, wpływ kąta na
    celność strzału oraz rozrzut reprezentacji na osiach Directness i Risk.
    Etykiety rozrzutu są mierzone i przesuwane, więc drużyny o zbliżonych
    wartościach nie nachodzą na siebie.
  • Strona ma osobne palety dla jasnego i ciemnego motywu; najsłabszy kontrast
    wynosi 4,9:1, a tekst ciągły 13,8:1.
  • Tools/build-and-deploy.sh dokłada stronę do paczek macOS i Windows jako
    ZASADY GRY.html, obok istniejącej LISTA ZMIAN.txt, i przerywa build, gdy
    pliku źródłowego brakuje. README-macOS.md w paczce wskazuje na nią jednym
    zdaniem.

  Poprawki:
  • Tekst w tabelach był czarny na ciemnym tle i praktycznie niewidoczny. Plik
    nie miał deklaracji <!DOCTYPE html>, więc otwarty prosto z rozpakowanego
    katalogu trafiał w tryb zgodności, w którym tabele nie dziedziczą koloru
    po elementach nadrzędnych. Strona jest teraz kompletnym dokumentem z
    <!DOCTYPE html>, lang="pl", <meta charset="utf-8"> i <meta
    name="viewport">, a reguła table ustawia color: inherit niezależnie od
    trybu.
  • Bez deklaracji kodowania polskie znaki zależały od zgadywania przeglądarki
    przy otwarciu z dysku; <meta charset="utf-8"> to przesądza.
  • Na wąskim ekranie cała strona przewijała się w poziomie zamiast przewijać
    samą tabelę. Elementy siatki mają domyślnie min-width: auto, więc kontener
    .table-scroll nie mógł się skurczyć poniżej szerokości treści. Siatki
    sekcji, kolumn i nagłówka używają teraz minmax(0, 1fr) i jawnego
    min-width: 0.
  • Opisy osi pionowej rozrzutu reprezentacji były przyklejone do lewej
    krawędzi i ucinane poza kadrem SVG („A BANQUE”, „EKURACJA”). Stoją teraz
    wyśrodkowane nad wykresem i pod nim, a opisy osi poziomej zeszły o wiersz
    niżej. Etykiety drużyn są dodatkowo przycinane do ramki, więc przy
    węższych marginesach żadna nie wychodzi poza rysunek.

Zasady rozgrywki spisane dla agentów
------------------------------------
26.07.2026, 19:45

  • Nowy .ai/GAMEPLAY-RULES.md opisuje mechanikę meczu tak, jak działa w
    kodzie: boisko i ustawienie startowe, model tury/rundy/aktywacji z
    punktami akcji, zasięg ruchu, stany piłki i krycie, pełne wzory na podanie
    z przechwytem, trzystopniowe rozstrzyganie strzału (celność, blok,
    bramkarz), warunki loba, model odbioru z czterema wynikami, osobne reguły
    bramkarza, wznowienie po golu, umiejętności i style reprezentacji oraz
    zasady determinizmu.
  • Każda liczba i reguła w dokumencie ma odnośnik do konkretnej linii kodu, z
    której pochodzi. Odnośniki są weryfikowalne skryptem — wszystkie 46
    wskazuje deklarację, którą opisują.
  • Dokument zawiera sekcję o granicy między regułą a prezentacją (BallMetrics
    mimo położenia w Core jest wyłącznie warstwą liczb do pokazania), listę
    pułapek (m.in. nieużywany BoardConfig.DiagonalStepCost) i zasady dla
    agenta zmieniającego mechanikę.
  • .ai/PROJECT-INSTRUCTIONS.md wskazuje na nowy dokument, ale go nie
    importuje przez @ — jest zbyt długi, żeby ładować go do kontekstu każdej
    sesji, więc agent otwiera go, gdy zadanie dotyczy mechaniki.

Styl gry reprezentacji: dane, komentarz i decyzje komputera
-----------------------------------------------------------
26.07.2026, 19:20

  • Każda reprezentacja ma teraz jawnie opisany styl gry: struktura TeamStyle
    w rdzeniu z czterema niezależnymi osiami w zakresie od -1 do 1 —
    Directness (cierpliwe rozgrywanie kontra piłka najkrótszą drogą), Risk
    (asekuracja kontra gra va banque), Aggression (głęboki blok kontra
    pressing) i Width (gra środkiem kontra gra skrzydłami). Styl opisuje
    wyłącznie zamiar drużyny, nie jej jakość: o tym, jak dobrze go realizuje,
    nadal decydują umiejętności zawodników.
  • TeamStyle wyznacza z siebie cechę wiodącą i drugorzędną (Dominant,
    Secondary) — najmocniejszą oś, o ile przekracza próg 0,30. Remisy
    rozstrzyga stała kolejność osi, więc wynik nie zależy od kolejności
    iteracji, a zmiana samych liczb automatycznie zmienia opis drużyny.
  • Wszystkie czternaście reprezentacji ma przypisane wartości spójne z ich
    profilami umiejętności: Włochy i Szwajcaria zachowawcze, Hiszpania na
    posiadaniu, Norwegia, Polska i Francja bezpośrednie, Argentyna i Meksyk
    pressingujące, Belgia, Brazylia i Portugalia ryzykowne, Anglia, Maroko i
    Holandia grające szerokością. Styl jest polem TeamDefinition i jest
    dostępny przez NationalTeams.Style.
  • Komentarz ma czwartą pulę zdań obok pozycji, reprezentacji i gwiazdy:
    szkołę futbolu, wybieraną po cesze wiodącej stylu. Pula jest celowo
    bezimienna (nie wymienia nazw krajów) i zawsze odzywa się jako ostatnia,
    więc ręcznie pisane kwestie narodowe nadal mają pierwszeństwo, a styl
    wypełnia momenty, dla których dana reprezentacja nie ma przygotowanego
    zdania.
  • Na rozpoczęciu meczu komentator nazywa starcie dwóch szkół futbolu,
    zestawiając cechy wiodące obu drużyn (osobne warianty dla drużyn o tym
    samym stylu). To jedyne miejsce, w którym styl mówi wprost, i pojawia się
    raz na mecz.
  • Rozpoznanie reprezentacji zawodnika liczone jest w komentarzu raz na
    zdarzenie i współdzielone przez pulę narodową i stylową; wcześniej ścieżka
    awaryjna przeszukiwałaby składy po nazwisku dwa razy.
  • Cała logika decyzyjna komputera mieszka teraz w osobnym pliku
    ComputerAi.cs zamiast na końcu MatchController.cs. MatchController tylko
    pyta, co zrobić, i to prezentuje; ComputerAi nie dotyka Unity, nie losuje
    z MatchState.Rng i niczego nie modyfikuje, więc pozostaje w pełni
    deterministyczne.
  • Komputer dobiera podanie z oceny ważonej — 45% szansa powodzenia, 40%
    postęp w stronę bramki, 15% swoboda odbiorcy — zamiast dotychczasowej
    reguły „najbardziej do przodu powyżej stałego progu". Dzięki temu bierze
    pod uwagę, czy podanie w ogóle ma szansę dojść, i potrafi zagrać wstecz,
    gdy do przodu nie ma nic sensownego.
  • Styl przesuwa tę ocenę o maksymalnie ±0,12 na znormalizowanej skali:
    Directness premiuje podania do przodu, Width odbiorcę przy linii bocznej.
    To wystarcza, żeby przestawić kolejność dwóch zbliżonych opcji, ale nigdy
    nie wypycha na czoło opcji wyraźnie gorszej.
  • Mocniej niż na ocenę styl wpływa na progi, bo to one odróżniają drużynę
    ryzykowną od zachowawczej. Próg podania to 0,42 − 0,12 × Risk, czyli od
    0,348 (Brazylia) do 0,504 (Szwajcaria). Zasięg, z jakiego komputer w ogóle
    rozważa strzał, to szerokość/3 + 2 × Risk w kratkach, czyli od 5 (Włochy,
    Maroko, Szwajcaria) do 7 (Norwegia, Argentyna, Belgia, Brazylia,
    Portugalia).
  • Komputer ocenia wszystkie komórki bramki i wybiera tę o największej
    szansie na gola, osobno dla strzału i dla loba; wcześniej celował zawsze w
    środek bramki, przez cały mecz w to samo miejsce.
  • Strzał i lob rozstrzyga jedno wspólne porównanie: lob musi być lepszy o
    0,06 − 0,04 × Directness, czyli od 0,028 (Norwegia) do 0,092 (Hiszpania).
    Wcześniej lob wygrywał zawsze, gdy tylko był legalny, bo stał pierwszy w
    wyrażeniu || — komputer praktycznie nie oddawał zwykłych strzałów.
  • Cel ruchu zależy od stylu: drużyna grająca szerokością kieruje zawodnika z
    piłką ku bliższej linii bocznej, a drużyna z ujemną agresją broni się
    cofnięciem — jej cel przesuwa się od posiadacza piłki w stronę własnej
    bramki, zamiast doskakiwać do rywala. Kara za wykorzystanie pełnego
    zasięgu ruchu to 0,08 − 0,05 × Directness, więc drużyny bezpośrednie
    biegają dłuższymi odcinkami niż cierpliwe.
  • Drużyna o agresji poniżej -0,25 (Włochy, Szwajcaria) rezygnuje z odbioru o
    szansie powodzenia poniżej 0,35, chyba że broni własnego pola karnego.
    Pozostałe reprezentacje atakują piłkę zawsze, jak dotąd.
  • Wybór aktywowanego zawodnika i wyprowadzenie piłki przez bramkarza celowo
    zostają bez wpływu stylu: pierwszy trzymają twarde priorytety chroniące
    przed zostawieniem bramkarza poza polem karnym, a przy drugim strata piłki
    jest na tyle kosztowna, że liczy się wyłącznie największa szansa
    powodzenia.
  • Komputer gra wyłącznie w trybie offline (ComputerTurnRoutine nie jest
    uruchamiane, gdy istnieje sesja sieciowa), a decyzje nie czerpią z
    generatora losowego meczu, więc zmiana nie dotyka ani synchronizacji w
    sieci, ani powtórek goli, które odtwarzają zapisane komendy.
  • Umiejętności zawodnika nadal nie wpływają na to, *jak trafnie* komputer
    wybiera — decydują dopiero o wykonaniu. Zaplanowana wariacja wyboru
    zależna od sumy umiejętności (kubełki najlepszy/średni/najgorszy) nie jest
    częścią tej zmiany.

Bramkarz reaguje dopiero w chwili uderzenia
-------------------------------------------
26.07.2026, 19:05

  Poprawki:
  • Przy strzale klasowego strzelca (IsEliteShooter) bramkarz rzucał się 0,68
    s przed samym uderzeniem, więc wyglądało to tak, jakby wiedział o strzale
    wcześniej. Wolej najpierw podbija piłkę
    (BallView.EliteVolleyPrepDuration), a reakcja bramkarza startowała już w
    momencie rozpoczęcia animacji. Rzut bramkarza jest teraz opóźniony o czas
    podbicia piłki, czyli zaczyna się dokładnie wtedy, gdy piłka wychodzi spod
    nogi.
  • Ta sama poprawka obejmuje złapanie piłki w pozycji stojącej, które również
    następowało przed uderzeniem.
  • Opóźnienie reakcji bramkarza liczy jedna metoda GoalkeeperReactionDelay
    używana zarówno przez strzały gracza, jak i komputera; wcześniej każda ze
    ścieżek miała własne wyliczenie i uwzględniała tylko loba.

Piłka opada z siatki także w powtórce gola
------------------------------------------
26.07.2026, 18:40

  Poprawki:
  • W powtórce gola piłka zostawała zawieszona w siatce przez cały czas
    przytrzymania ujęcia, mimo że w normalnej grze od razu opadała na murawę.
    Powtórka kontynuuje teraz ten sam profil opadania, którego używa gra na
    żywo (BallView.EvaluateNetDropPosition), rozciągnięty na 0,5 s, więc piłka
    leży już na trawie, zanim reżyser przetnie na kolejne ujęcie. Dotyczy obu
    ujęć powtórki oraz goli strzelonych lobem.
  • Miejsce, w którym piłka wyhamowuje po wpadnięciu w siatkę (razem z
    odbiciem od siatki w stronę boiska), liczy jedna wspólna metoda
    BallView.NetDropGround, używana i przez grę na żywo, i przez powtórkę.

Pomiar uderzenia tylko przy wyjątkowych strzałach i rzadkie strzały rekordowe
-----------------------------------------------------------------------------
26.07.2026, 18:05

  • Komentator nie podaje już dystansu i prędkości przy każdym strzale. Liczby
    pojawiają się tylko wtedy, gdy uderzenie faktycznie na to zasługuje: z co
    najmniej 30 metrów albo przy prędkości od 115 km/h w górę, a przy jednym i
    drugim naraz komentarz jest osobny i najbardziej entuzjastyczny.
  • Zamiast suchej formuły „Pomiar uderzenia" komentator wyraża podziw — dla
    każdego z trzech przypadków (daleko, mocno, daleko i mocno) są po trzy
    warianty zdania.
  • Bardzo rzadko piłka wychodzi spod nogi z prędkością rekordową: 4,5% szans
    przy strzale (nie lobie) z minimum 20 metrów przez zawodnika o
    umiejętności strzału co najmniej 0,72. Prędkość takiego uderzenia mieści
    się wtedy w przedziale 150–208 km/h, z rozkładem faworyzującym dolną część
    zakresu, więc wartości bliskie rekordowi świata są wyjątkowe.
  • Przy takim strzale komentarz odwołuje się do prawdziwych rekordów: powyżej
    200 km/h do 210,9 km/h Ronny'ego Hebersona z 2006 roku, powyżej 185 km/h
    do Robbena, Reida i Koemana, a powyżej 150 km/h do oficjalnego rekordu
    Galana Marina, wolnego Roberto Carlosa oraz goli Trezegueta i Yeboaha.
    Każdy próg ma trzy warianty zdania.
  • Losowanie strzału rekordowego jest deterministyczne: ziarno powstaje z
    identyfikatora strzelca, pól startowego i docelowego, numeru rundy i sumy
    bramek, więc obaj gracze widzą tę samą prędkość bez przesyłania
    dodatkowych danych. ShotSpeedKmh przyjmuje ziarno jako opcjonalny
    parametr, a ziarno równe zero wyłącza mechanizm.
  • Animacja lotu piłki jest teraz wyliczana z tej samej zmierzonej prędkości,
    którą podaje komentator i którą zapisują statystyki, więc obie liczby nie
    mogą się rozjechać. GetShotFlightDuration nie liczy już własnej mocy z
    umiejętności strzału i miejsca na zamach — te czynniki są już zaszyte w
    km/h — a zostaje jedynie osłabienie przy strzale spod bardzo ostrego kąta.
    Stała ShotSpeedStrongest opisuje odtąd prędkość lotu odpowiadającą górze
    normalnego zakresu (145 km/h), a wszystko wolniejsze i szybsze skaluje się
    proporcjonalnie.
  • Strzał rekordowy ma niższą dolną granicę czasu lotu (0,11 s zamiast 0,18
    s), więc widać, że piłka leci szybciej niż przy każdym innym uderzeniu.
    Obroniony strzał zachowuje dotychczasowe widełki 0,24–0,44 s, żeby
    animacja interwencji bramkarza pozostała czytelna.
  • Prędkość nadal nie ma żadnego wpływu na skuteczność strzału: wynik
    rozstrzyga deterministyczny rdzeń, zanim cokolwiek zostanie wyświetlone.
  • Podbity UUID klienta (GameplayBuildUuid), bo starszy klient policzyłby dla
    tego samego strzału inną prędkość i inny czas lotu.

Cieńsza ramka flag reprezentacji
--------------------------------
26.07.2026, 17:40

  • Flagi reprezentacji w interfejsie mają czarną ramkę i cień o grubości
    jednego piksela zamiast trzech, a sama flaga wypełnia niemal cały kafelek.
    Grubość jest jedną stałą w NationalFlagUi, więc dotyczy wszystkich miejsc:
    HUD meczu, raportu meczu, ekranu statystyk i menu głównego.
  • Zapasowa flaga rysowana z kształtów UI (używana, gdy nie ma zaimportowanej
    tekstury) skaluje się do rzeczywistego rozmiaru kafelka zamiast pozostawać
    na sztywnych 60x36, więc nie zostawia już szarego marginesu wokół rysunku.

  Poprawki:
  • Kafelki flag w pasku wyniku, menu głównym, prezentacji przedmeczowej,
    raporcie meczu i na ekranie statystyk miały grubą czarną obwódkę. Składały
    się na nią trzy rzeczy: cień Outline doklejany na zewnątrz kafelka, ramka
    tła oraz przezroczysty margines zapieczony w plikach flag (1/24 szerokości
    i 1/15 wysokości na każdej krawędzi), przez który prześwitywała ciemna
    płytka pod spodem. Cień został usunięty, a tekstura jest powiększana o ten
    margines, więc sama flaga sięga krawędzi kafelka.
  • Cztery klasy interfejsu zawierały nieosiągalny kod za instrukcją return —
    stare kopie rysowania flag sprzed przejścia na NationalFlagUi, razem z
    nieużywanymi już pomocnikami AddFlagPiece i Piece. Kompilator zgłaszał z
    tego powodu ostrzeżenie CS0162.

Pełny kadr i elektryczna przekątna prezentacji meczu
----------------------------------------------------
26.07.2026, 17:10

  • Niebieska przekątna jest renderowana na pierwszym planie ponad
    pełnoekranowym przyciemnieniem, z bezpośrednio użytym assetem
    Textures/ShotEnergyTrail. Dwie szerokie, ciasno wykadrowane warstwy
    energii niezależnie przewijają teksturę i pulsują grubością, a osobne
    poświata i jasny rdzeń utrzymują czytelną oś podziału. Całość łagodnie
    wygasza się podczas rozsuwania kart.

  Poprawki:
  • Ciemne przyciemnienie ekranu prezentacji przed meczem miało sztywny
    rozmiar 1920x1080 i przy nietypowych proporcjach ekranu nie zakrywało
    całego kadru — teraz rozciąga się na 100% powierzchni canvasu.
  • Linie siatki taktycznej i ukośna linia dzieląca urywały się przed
    krawędzią ekranu na szerokich i wysokich rozdzielczościach; linie siatki
    rozciągają się wzdłuż własnej osi, a ich zakres i długość linii dzielącej
    sięgają poza proporcje 16:9.
  • Niebieska linia dzieląca korzystała ze stałego kąta -19°, więc tylko w
    przybliżeniu pokrywała się z boiskiem. Jej środek i obrót są teraz
    wyprowadzane z ekranowej projekcji narożników (0,0) i
    (szerokość,wysokość), dzięki czemu w domyślnym ustawieniu kamery
    przechodzi przez właściwą przekątną murawy na każdym formacie ekranu i
    rozmiarze planszy.
  • Światowy LineRenderer znajdował się pod kryjącym w 87% overlayem, przez co
    na ekranie pozostawał jedynie bardzo słaby, cienki ślad. Efekt wrócił na
    warstwę pierwszego planu, a pionowe UV assetu są ciasno przycięte wokół
    rzeczywistego filamentu zamiast skalować 512 pikseli pustej
    przezroczystości — prąd jest dzięki temu duży, kontrastowy i wyraźnie
    animowany.

Repozytorium Git z czytelną, liniową historią i dziennymi punktami wycofania
----------------------------------------------------------------------------
26.07.2026, 16:50

  • Projekt jest objęty kontrolą wersji Git na głównej gałęzi main; źródła,
    ustawienia projektu, dokumentacja i narzędzia trafiają do pierwszego
    commita, a odtwarzalne cache'e Unity, lokalne buildy, logi, pliki
    tymczasowe i artefakty wdrożeniowe są wykluczone.
  • Każde zakończone zadanie ma własny commit na main z komunikatem
    podsumowującym rezultat wpisu w changelogu. Poprawki w ramach nadal
    trwającego zadania aktualizują ten commit przez amend zamiast tworzyć
    kolejne drobne commity.
  • Historia main pozostaje liniowa: gałęzie zadaniowe są dozwolone, ale
    trafiają na main wyłącznie przez fast-forward, bez commitów merge.
  • Po zakończeniu zadania agent automatycznie tworzy tag w formacie
    YYYY-MM-DD; jeżeli dzienny tag już istnieje, przesuwa go na najnowszy
    commit, zapewniając jeden aktualny punkt wycofania dla każdego dnia pracy.
  • Commity i opcjonalne gałęzie zadaniowe używają wspólnego schematu
    <typ>(<obszar>): podsumowanie oraz <typ>/<obszar>-<nazwa>. Zamknięta lista
    typów rozróżnia funkcje, poprawki, refaktoryzacje, assety, dokumentację,
    buildy, testy i utrzymanie, a obszary wskazują m.in. gameplay, AI,
    interfejs, powtórki, sieć, serwer i narzędzia.
  • Typ opisuje charakter pracy, a obszar część projektu: zmiana mechaniki
    jest na przykład feat(gameplay) albo fix(gameplay), zamiast tworzyć
    niejednoznaczny typ gameplay. Instrukcja zawiera gotowe przykłady dla
    najczęstszych zmian.

naprawa błędów bazy i lokalny czas w logach
-------------------------------------------
26.07.2026, 16:30

  Poprawki:
  • Tabela goals w bazie statystyk nie miała kolumny team_name, przez co
    zapytania Detail() i TopScorers() zgłaszały błąd „no such column:
    team_name". Dodano team_name TEXT NOT NULL DEFAULT '' do schematu; stare
    bazy otrzymają kolumnę przez ALTER TABLE przy pierwszym uruchomieniu.
  • Wpisywanie meczu nie zapisywało team_name w tabeli goals, przez co
    istniejące rekordy bramek zwracały puste nazwiska. Zaktualizowano INSERT
    na stats.go:527 tak, by przechowywał team_name z raportu.
  • Logi serwera pokazywały czas UTC zamiast lokalnego. Usunięto log.LUTC z
    main.go:203, teraz timestampy w logach odpowiadają czasowi serwera.

Powiewające flagi reprezentacji w narożnikach boiska
----------------------------------------------------
26.07.2026, 16:10

  • W czterech narożnikach boiska stoją teraz małe chorągiewki: dwa narożniki
    na bronionej połowie pokazują flagę danej reprezentacji.
  • Chorągiewki korzystają z tych samych importowanych tekstur flag co
    interfejs, są widoczne z obu stron i delikatnie falują na lekkiej,
    proceduralnie animowanej siatce; ruch jest wyłącznie kosmetyczny i nie
    dotyka fizyki ani determinizmu meczu.
  • Maszty stoją na osiach linii narożnych i mają rzeczywiste proporcje
    przeliczone tą samą skalą co zawodnicy i bramki: 170 cm wysokości oraz
    materiał 56 × 44 cm.
  • Materiał każdej chorągiewki kieruje się ukośnie od środka boiska, więc w
    każdym narożniku w całości powiewa na zewnątrz pola gry.
  • Proste drzewce bez ozdobnej kulki są jednolicie pomalowane czytelnym
    kolorem swojej reprezentacji; drużyny z jasnym albo białym strojem używają
    narodowego koloru detali. Maszty nie mają napisów ani odstających
    elementów.

Jedna metoda kolorowania barwami reprezentacji na stronach statystyk i meczu
----------------------------------------------------------------------------
26.07.2026, 16:00

  • Kolorowanie barwami reprezentacji jest jednym modułem współdzielonym przez
    stronę statystyk i raport meczu: zmienne --team-*, klasy .tc-* (tekst) i
    .tb-* (tło pasków statystyk) oraz funkcje applyTeamColor(),
    colorizeSides(), teamSlug() i teamColorClass(). Obie strony miały
    wcześniej własne kopie map kolorów i własne wyliczanie stroju wyjazdowego.
  • Historia spotkań dostaje z serwera tę samą listę bramek co szczegóły meczu
    (statsStore.goals()), a kolumna STRZELCY jest renderowana jako osobne
    elementy z data-team-name zamiast jednego napisu parsowanego potem w
    przeglądarce. Nazwiska strzelców kolorują się tą samą metodą co
    pseudonimy, razem ze zmianą stroju gościa.
  • Pasek ostatnich wyników buduje nazwiska z tymi samymi atrybutami
    data-team-name/data-side co tabele i koloruje je tym samym
    colorizeSides(), razem ze zmianą stroju gościa. Pseudonimy są przy tym
    escapowane, bo to jedyne miejsce, gdzie strona składa HTML z danych gracza
    po stronie przeglądarki.
  • Endpoint v1/stats/matches zwraca bramki meczu w polu goals — w tej samej
    strukturze co szczegóły meczu.
  • Barwy reprezentacji są klasami CSS (.tc-<drużyna> i .tc-<drużyna>-away)
    zdefiniowanymi obok zmiennych --team-*, zamiast kolorów wyliczanych w
    JavaScripcie i wstawianych inline.
  • Jedna uniwersalna funkcja applyTeamColor(element, opts) koloruje dowolny
    element na podstawie data-team-name (z data-team jako zapasem dla starych
    meczów i data-side dla nieznanej drużyny). Korzystają z niej historia
    spotkań, tabela strzelców, rekordy, lista strzelców w wierszu meczu i
    pasek ostatnich wyników — wcześniej każde z tych miejsc miało własną kopię
    map kolorów.
  • Tabela rekordów jest kolorowana tak samo jak tabela strzelców i pokazuje
    polskie nazwy reprezentacji.
  • Gość zmienia komplet strojów na wyjazdowy wszędzie tam, gdzie oba komplety
    by się zlewały — także przy nazwiskach strzelców i w pasku wyników.

  Poprawki:
  • Pseudonimy gospodarzy i gości oraz strzelcy w historii spotkań nie były
    kolorowane w ogóle: skrypt kończył się nadmiarowym nawiasem klamrowym,
    więc cały blok nie parsował się i colorizeHistoryNames nie istniało.
  • Kolorowanie strzelców czytało pola TeamName/Team z JSON-a bramek, który
    używa nazw teamName/team, więc każdy strzelec dostawał kolor gościa. Pole
    team bramki jest stroną meczu (0/1), a nie reprezentacją — numer
    reprezentacji brany jest teraz z wiersza meczu.
  • Domknięto obciętą regułę .elo-table td { na końcu arkusza stylów.
  • Migracja bazy dotyczyła wyłącznie tabeli matches, więc kolumna
    goals.team_name powstawała tylko w nowej bazie — istniejąca baza zwracała
    „no such column: team_name" i strona statystyk kończyła się błędem 500.
    migrate() przechodzi teraz po mapie tabela → dobrane kolumny i dokłada
    brakujące w każdej z nich.

Losowane wzory i trzy odcienie murawy
-------------------------------------
26.07.2026, 15:50

  • Murawa korzysta teraz z trzech osobnych tekstur trawy o jasnym, średnim i
    ciemnym odcieniu; każda zachowuje drobny detal źdźbeł bez zaszytego w
    bitmapie wzoru koszenia.
  • Przed zbudowaniem prezentacji każdego meczu losowany jest jeden z czterech
    wyglądów boiska: czyste jasne pole, naprzemienne jasne i średnie pasy
    wzdłużne, takie same pasy poprzeczne albo trójkolorowa kratka.
  • Pasy obu orientacji mają dokładnie dwie pełne kratki szerokości i
    pokrywają się z granicami logicznej siatki; w kratce każdy kolorowy
    kwadrat ma rozmiar jednego pola gry.
  • Trójkolorowa kratka odwzorowuje krzyżowe koszenie z referencji i powtarza
    kafel 2 × 2: jasny–średni / średni–ciemny; każde jasne pole graniczy
    bokami wyłącznie ze średnimi, a po przekątnych z ciemnymi, więc jasne pola
    nie tworzą ukośnych łańcuchów.
  • Wzór jest składany z bezkolizyjnych pól wizualnych nad jednym ciągłym
    colliderem boiska, więc nie zmienia klikania pól, siatki logicznej ani
    linii; osobny generator losowości prezentacji nie wpływa na
    deterministyczny stan meczu i multiplayer.
  • Tekstury powtarzają się według stałej skali świata zamiast rozciągać jedną
    bitmapę na całe boisko, dzięki czemu detal trawy pozostaje wyraźny we
    wszystkich czterech wzorach.

Ramki podium na liście strzelców
--------------------------------
26.07.2026, 15:20

  • Pierwsze trzy wiersze listy strzelców są wyróżnione pełną ramką podium:
    złotą dla lidera, srebrną dla drugiego miejsca i brązową dla trzeciego.
    Dotyczy to statystyk lokalnych i sieciowych.
  • Lider listy strzelców nie jest już barwiony na złoto; jego nazwa, tak jak
    nazwy pozostałych strzelców, używa barwy reprezentacji.

Rankingi w statystykach sieciowych
----------------------------------
26.07.2026, 15:19

  • Statystyki sieciowe w kliencie mają nową zakładkę „Ranking”, pobierającą
    bieżące dane ELO bezpośrednio z endpointu lobby /v1/elo-ranking. Tabela
    pokazuje pozycję, rating, tygodniową zmianę ratingu i miejsca oraz pełne
    zestawienie meczów, bramek i meczów domowych/wyjazdowych.
  • Zakładka jest dostępna tylko dla statystyk sieciowych, także przez L1/R1;
    w widoku lokalnym nie zajmuje miejsca na pasku kart.
  • Krótkie etykiety „Tabela” i „Ranking” mieszczą się w kartach paska
    nawigacji.
  • Kolory obu rankingów są teraz wyliczane dokładnie według zasad strony
    lobby: najlepsza ćwiartka różnych wartości przechodzi od zieleni do
    jasnego atramentu, najsłabsza od czerwieni do przygaszonej zieleni, a
    środek pozostaje neutralny. Zwykły ranking używa punktów, ELO ratingu;
    tygodniowe wzrosty i spadki ELO zachowują odpowiednio zielony i czerwony
    kolor, a nowe wpisy złoty.

Czytelniejszy nagłówek i równe liczby w raporcie meczu
------------------------------------------------------
26.07.2026, 15:12

  • Nagłówek raportu meczu układa teraz nazwy reprezentacji, flagi i wynik na
    jednej wysokości. Nazwy oraz flagi są większe i znajdują się bliżej
    wyniku, dzięki czemu zestawienie obu drużyn jest czytelniejsze.

  Poprawki:
  • Liczby gospodarza przy paskach statystyk mają teraz taki sam odstęp od
    wykresu jak liczby gościa; wcześniej dotykały krawędzi paska.

Zasady serwera i rankingu spisane dla agentów
---------------------------------------------
26.07.2026, 12:40

  • Powstał server/AGENTS.md z regułami obowiązującymi w kodzie serwera: układ
    katalogu, zasady edycji warstwy WWW (pliki w web/, //go:embed, adresy
    względne i <base>, kolejność arkuszy, zakładki jako osobne adresy,
    data-tip, jedno wejście do kolorowania barwami reprezentacji), zasady obu
    rankingów wraz z ELO i ruchem tygodniowym od poniedziałku, obsługa
    migracji bazy oraz kiedy podbijać UUID serwera. Osobny plik, bo te reguły
    dotyczą wyłącznie serwera i nie mają sensu w kodzie gry.
  • Spisane zostały też znane ograniczenia, żeby kolejny agent nie brał ich za
    błędy do naprawienia: kolumny średnich w ELO dublują aktualną pozycję i
    ranking, CalculateEloRanking() ignoruje limit, a teamStrengths jest ręczną
    kopią wartości z NationalTeams.cs.
  • server/lobby/README.md opisuje aktualny stan strony: adresy zakładek,
    warstwę przeglądarki w plikach web/, generowane barwy reprezentacji i
    zasady rankingu ELO. Wcześniej twierdził, że strona działa bez
    JavaScriptu.

Własne podpowiedzi na stronie statystyk
---------------------------------------
26.07.2026, 12:25

  • Nagłówki kolumn mają własny dymek zamiast natywnego title przeglądarki:
    styl strony, bez systemowego okienka i bez sekundowego opóźnienia. Treść
    podaje atrybut data-tip.
  • Dymek jest jednym elementem doklejanym do <body> i ustawianym z
    JavaScriptu (position: fixed), więc nie przycina go przewijana w poziomie
    tabela — na czym poległby dymek zbudowany na ::after przy nagłówku.
    Ustawia się nad elementem, a przy górnej krawędzi okna pod nim, i sam
    trzyma się w oknie; strzałka nadal celuje w element, którego dotyczy.
  • Podpowiedź pokazuje się też przy przejściu klawiaturą i znika po Escape.
    Na urządzeniach dotykowych nie pojawia się wcale, żeby nie zasłaniać tego,
    w co użytkownik celuje palcem.

Tygodniowy ruch w rankingu ELO
------------------------------
26.07.2026, 12:10

  • Ranking ELO pokazuje ruch tygodniowy w dwóch kolumnach: ZM. PKT (zmiana
    rankingu) i ZM. POZ. (zmiana miejsca w tabeli), liczony od poniedziałku
    00:00 czasu serwera. W poniedziałek rano wszystkim zeruje się licznik i
    tydzień zaczyna się od nowa.
  • Zmiana pozycji ma znak czytany jak w tabeli: +2 to dwa miejsca w górę.
    Wzrosty są zielone, spadki czerwone, a gracz, który przed tym tygodniem
    nie był jeszcze notowany, ma NOWY zamiast liczby, bo nie ma z czym
    porównywać.
  • CalculateEloRanking() fotografuje stan tabeli tuż przed pierwszym meczem
    bieżącego tygodnia i porównuje z nim stan końcowy. Endpoint v1/elo-ranking
    zwraca positionChange i new obok istniejącego ratingChange.
  • Panel rankingu i podpowiedzi obu kolumn podają konkretną datę
    poniedziałku, od którego liczony jest bieżący tydzień.
  • Kolejność tabeli rozstrzyga teraz remis punktowy nazwą gracza, więc dwaj
    gracze z tym samym rankingiem nie zamieniają się miejscami między
    odświeżeniami — bez tego zmiana pozycji potrafiłaby migać przy zerowym
    ruchu.

  Poprawki:
  • Tabela ELO nie miała kolorowanych pozycji zaraz po wejściu na stronę — jej
    wiersze dochodzą z serwera już po pomalowaniu panelu, więc kolorowanie
    zastawało pustą tabelę i działało dopiero po kliknięciu w zakładkę. Kolory
    nakładane są teraz zaraz po wstawieniu wierszy.
  • Kolumna zmiany tygodniowej pokazywała 0 dla wszystkich: pole RatingChange
    było zadeklarowane, ale nigdy nie wyliczane.

Lob na czele listy akcji z szansą na gola
-----------------------------------------
26.07.2026, 12:09

  • Kolejność akcji w panelu jest jedna dla wszystkich zawodników: „Lob”,
    „Strzał”, „Podanie”, „Odbiór”, „Cofnij ruch”, „Zakończ turę”. Lob pojawia
    się tylko w rzadkiej sytuacji wyjścia bramkarza, więc gdy jest legalny,
    stoi na samej górze. Zniknęło osobne ustawienie dla napastnika, bo strzał
    i tak jest teraz zawsze nad podaniem.
  • Przycisk „Lob” podaje szansę na gola (LOB • 42%) i jest malowany paletą
    BoardView.SuccessChanceColor, tą samą, którą tarcze w bramce pokazują
    jakość celu — od czerwonego przy akcji bez szans do zielonego przy pewnym
    golu. Bez dostępnego loba przycisk wraca do niebieskiego stylu listy.
  • GameHud.SetSelecting nie przyjmuje już flagi isForward, a szansę loba
    ustawia osobne GameHud.SetLobChance, symetrycznie do SetTackleChance.

Zakładki statystyk jako osobne adresy
-------------------------------------
26.07.2026, 11:55

  • Każda zakładka strony statystyk ma własny adres: stats/elo, stats/history,
    stats/scorers, stats/records, stats/downloads, stats/ranking. Serwer
    otwiera od razu właściwy panel, więc wysłany komuś odnośnik nie ląduje na
    tabeli i nie mruga zawartością przy wczytaniu.
  • Przełączanie zakładek nadal nie przeładowuje strony — adres podmienia
    history.pushState(), a cofanie i chodzenie do przodu w przeglądarce wraca
    do właściwej zakładki.
  • Zakładki są odnośnikami zamiast przycisków, więc można je kopiować i
    otwierać w nowej karcie (ctrl/shift/środkowy przycisk działają normalnie).
  • Stare odnośniki z fragmentem (stats#elo) dalej działają: strona otwiera tę
    zakładkę i po cichu podmienia adres na nowy.
  • Strona podaje <base> wskazujący katalog usługi, dzięki czemu adresy
    względne (zapytania API, arkusze, raporty meczów, pobierania) działają tak
    samo na stats i na stats/elo. Nieznana zakładka przekierowuje na stats,
    zachowując filtr gracza.
  • Odnośniki do meczów danego gracza prowadzą wprost do
    stats/history?player=….

Front-end strony statystyk w osobnych plikach, barwy generowane z gry
---------------------------------------------------------------------
26.07.2026, 11:40

  • HTML, CSS i JavaScript obu stron WWW mieszkają w server/lobby/web/ jako
    zwykłe pliki (stats.html, stats.css, stats.js, match.html, match.css,
    match.js, team-colors.css, team-colors.js) zamiast surowych stringów w
    kodzie Go. Trafiają do binarki przez //go:embed, więc wdrożenie to nadal
    jeden plik do skopiowania, ale edytor, formatter i linter widzą je jako
    HTML/CSS/JS.
  • Szablony stron ładowane są przez template.ParseFS, a arkusze i skrypty
    serwuje serveWebAsset pod assets/*.css i assets/*.js. Adresy niosą wersję
    builda (?v=), więc przeglądarka może je trzymać w cache na stałe i dostaje
    nowe od razu po wgraniu nowej binarki.
  • Barwy reprezentacji nie są już przepisywane ręcznie:
    Tools/gen-team-colors.py generuje web/team-colors.css i blok danych w
    web/team-colors.js wprost z Assets/Scripts/Game/NationalTeams.cs, licząc
    kolor tak samo jak TeamKit.InterfaceColor. Tryb --check mówi, czy pliki są
    aktualne.
  • Kolory na stronie odpowiadają teraz dokładnie tym, które gra pokazuje w
    swoim interfejsie. Najbardziej widoczna zmiana to Francja: granatowa
    koszulka ma luminancję poniżej progu, więc — tak jak w grze — reprezentuje
    ją jasnoniebieski detal zamiast granatu.
  • Arkusz team-colors.css ładowany jest po arkuszu strony, bo klasy kitów
    mają tę samą specyficzność co .win czy .assist i muszą wygrywać
    kolejnością.

ELO ranking i siły drużyn
-------------------------
25.07.2026, 16:45

  Nowości:
  • ELO ranking system dla graczy w serwerze lobby
  • Każdy gracz zaczyna z 1000 punktów ELO
  • Ranking obliczany na podstawie wyników meczów
  • Nowa zakładka "RANKING ELO" w statystykach serwera
  • Tabela ELO pokazująca: pozycję, pseudonim, ranking, średnią pozycję,
    średni ranking, zmianę tygodniową, wszystkie mecze, domowe, wyjazdowe,
    wygrane, przegrane, bramki zdobyte i stracone
  • Wartości siły drużyn w Assets/Scripts/Game/NationalTeams.cs
  • Siły drużyn uczestniczą w wyliczeniu wyniku pojedynku, nie tylko ranking
  • Im większa różnica sił, tym większy wpływ na wynik meczu

Pasek komentarza znika na czas powtórki
---------------------------------------
25.07.2026, 15:12

  Poprawki:
  • Powtórka gola nie pokazuje już paska komentarza. Wcześniej odtwarzanie
    zapisanego gola szło tą samą ścieżką prezentacji co gra na żywo, więc
    dopisywało linie do paska, a ten wystawał zza czarnych pasów powtórki.
  • Pasek jest chowany na czas powtórki zapisanej i pozostaje schowany po
    powrocie wskaźnika powtórki na żywo, dopóki tryb powtórki trwa. Dodatkowo
    HUD odrzuca każdą linię komentarza, która trafi do niego w czasie powtórki
    — to, co powtórka pokazuje, zostało już skomentowane wtedy, gdy się
    wydarzyło.

Dystans i siła uderzenia: pomiary w pojedynku i rekordy w statystykach
----------------------------------------------------------------------
25.07.2026, 14:39

  • BallMetrics przelicza planszę na metry (105 m x 68 m dla siatki 18x12) i
    wyznacza siłę strzału w km/h z umiejętności strzeleckiej, dystansu i tego,
    czy było to uderzenie czy lob. Wszystkie wartości są wyłącznie poglądowe:
    powstają z akcji już rozstrzygniętej przez symulację, więc oba klienty
    liczą to samo i nic nie wpływa na wynik.
  • Panel pojedynku pokazuje pod nazwą akcji dystans w metrach dla podania i
    dla strzału. Siły przed kopnięciem nie widać, bo przed uderzeniem nikt jej
    nie zna.
  • Siła uderzenia trafia do komentarza po oddaniu strzału — zdanie zamyka
    pomiar dystansu i prędkości. Dotyczy strzałów i lobów, nie podań.
  • Statystyki meczu zbierają rekordy z akcji celnych: najdalszy i
    najsilniejszy strzał (uderzenie, które co najmniej zmusiło bramkarza do
    interwencji) oraz najdalsze celne podanie, każdy z nazwiskiem wykonawcy.
  • Raport meczu — w grze i na stronie meczu w lobby — ma trzy nowe wiersze
    porównania: najdalszy strzał (m), najsilniejszy strzał (km/h) i najdalsze
    podanie (m). Tabela zmieściła je przez zagęszczenie wierszy i wyższy
    panel.
  • Ekran statystyk ma nową zakładkę REKORDY, w obu zakresach: lokalnym
    (rekordy zapisane na tym urządzeniu, obok tabeli strzelców) i sieciowym
    (rekordy wszech czasów z serwera). Zakładki układają się teraz
    automatycznie na dowolną ich liczbę w danym zakresie.
  • Serwer przyjmuje rekordy w raporcie meczu, przechowuje je w nowych
    kolumnach tabeli matches (migracja ALTER TABLE, stare mecze mają zera),
    waliduje ich zakres i odrzuca rekord bez nazwiska. Nowy endpoint GET
    /v1/stats/records oraz zakładka REKORDY na stronie statystyk podają
    aktualnego rekordzistę każdej kategorii z odnośnikiem do meczu.
  • UUID protokołu serwera podbity, bo raport meczu przenosi nowe dane, a
    klient czyta nowy endpoint.

Skrypt sprawdzania i importowania assetów reprezentacji
-------------------------------------------------------
25.07.2026, 14:00

  • Dodano skrypt Tools/team-assets.py do zarządzania assetami per
    reprezentacja.

Teksturowane flagi z narodowym fallbackiem
------------------------------------------
25.07.2026, 13:17

  • Flagi reprezentacji na ekranach menu, meczu, raportu i statystyk
    korzystają z jednego loadera tekstur. Plik
    Assets/Resources/UI/Flags/<NazwaReprezentacji>.png automatycznie zastępuje
    grafikę dla odpowiadającej mu wartości NationalTeam.

  Poprawki:
  • Brak zaimportowanej tekstury nie pokazuje już tej samej niebieskiej flagi
    ONZ dla wszystkich drużyn. Loader buduje wówczas uproszczoną, ale właściwą
    flagę każdej z czternastu reprezentacji z elementów UI.

Delikatna poświata wokół nazw reprezentacji
-------------------------------------------
25.07.2026, 12:21

  • Nazwy reprezentacji pisane kolorem kitu mają jednopikselową,
    półprzezroczystą poświatę w tonie przeciwnym do koloru fontu: jasny font
    dostaje ciemną krawędź, ciemny rozjaśnioną wersję własnego koloru. Sam
    napis zachowuje barwę narodową, a ciemne kolory nie zlewają się już z
    czarnym paskiem wyniku.
  • Efekt stosowany jest wyłącznie przy nazwach drużyn na pasku wyniku. Panel
    podsumowania meczu i nazwisko w panelu pojedynku zostają bez poświaty.
  • UiSupport.ApplyContrastOutline dobiera kolor poświaty z jasności koloru
    tekstu, więc kolejne miejsca z kolorami reprezentacji mogą korzystać z tej
    samej reguły.

Statystyki lokalne i sieciowe pod jednym ekranem
------------------------------------------------
25.07.2026, 11:50

  • Ekran statystyk ma teraz nadrzędny podział na LOKALNE i SIECIOWE, a
    dopiero pod nim zakładki widoku: TABELA (tylko sieciowo — lokalnie nie ma
    kont do porównania), STRZELCY i HISTORIA MECZÓW. L1/R1 przełączają
    zakładki w obrębie wybranego zakresu. Przełączenie zakresu otwiera jego
    główny widok: TABELA dla sieciowego, STRZELCY dla lokalnego. Oba rzędy
    przycisków tworzą jeden blok o wspólnych krawędziach: zakładki mają stałą
    szerokość niezależnie od tego, czy jest ich dwie czy trzy; przy dwóch lewa
    kończy się dokładnie tam, gdzie LOKALNE, a prawa zaczyna się tam, gdzie
    SIECIOWE, przy trzech skrajne trzymają się zewnętrznych krawędzi bloku.
  • Strzelcy lokalni i sieciowi korzystają z jednej tabeli o tych samych
    kolumnach, łącznie z MECZE. Lokalnie mecze liczone są tak samo jak na
    serwerze: jeden mecz na zawodnika, który w nim strzelił albo asystował,
    niezależnie od liczby akcji. Lista lokalna obejmuje też zawodników z
    samymi asystami.
  • Statystyki kariery zapisują liczbę takich meczów przy każdym zawodniku, a
    starsze zapisy bez tego pola są jednorazowo uzupełniane z lokalnej
    historii spotkań. Zawodnik spoza zachowanej historii pokazuje kreskę
    zamiast zaniżonej liczby.
  • Lokalna historia spotkań trzyma 666 ostatnich meczów zamiast 30, więc
    uzupełnianie liczby meczów sięga znacznie głębiej.
  • Osobny ekran „STATYSTYKI WSZECH CZASÓW" z dwiema tabelami (strzelcy i
    asystenci) zniknął z menu głównego. Przycisk STATYSTYKI otwiera wspólny
    ekran w zakresie lokalnym.
  • CareerStatisticsData udostępnia TopContributors, czyli jedno zestawienie
    posortowane po golach i asystach, zamiast dwóch osobnych list na potrzeby
    prezentacji.

Tabela statystyk bez remisów i z pełnymi nazwami kolumn
-------------------------------------------------------
25.07.2026, 11:20

  • Mecz nie może zakończyć się remisem, więc tabela wyników nie ma już
    kolumny remisów: ani na stronie statystyk serwera, ani na ekranie
    statystyk w grze.
  • Ranking serwera nie zwraca już pola drawn, a punkty liczy wyłącznie po
    zwycięstwach (3 punkty za wygraną).
  • Tabela w grze pokazuje pełne nagłówki MECZE, ZWYCIĘSTWA i PORAŻKI zamiast
    jednoliterowych skrótów; kolumny rozstawiono na nowo, aby zmieściły się
    obok siebie.
  • Strona statystyk pokazuje pełne nazwy kolumn od szerokości 720 px, a na
    węższych ekranach zostaje przy skrótach.
  • Nagłówki paneli, zakładki i nicki graczy na stronie statystyk oraz na
    stronie pojedynczego meczu używają Handel Gothic — tego samego kroju co
    menu w grze. Font jest wkompilowany w binarkę i serwowany z
    /assets/handel-gothic.ttf.
  • Strona meczu ma dokładnie ten sam nagłówek co strona statystyk: podtytuł,
    kafelki z podsumowaniem, komplet czterech zakładek i tę samą szerokość
    treści, więc przejście między stronami nie przesuwa menu.
  • Podbity UUID protokołu serwera i klienta, ponieważ zmienił się format
    danych rankingu.

Telewizyjna prezentacja i muzyczne wejście w mecz
-------------------------------------------------
25.07.2026, 09:30

  • Każdy nowy mecz zaczyna się telewizyjnym ekranem zapowiedzi rozłożonym na
    wyraźnie przyciemnionym boisku z subtelną siatką taktyczną i ukośną
    świetlną linią. Obie strony korzystają z jednego stałego szablonu karty
    410×520: neutralnego ciemnego szkła bez barwnego wypełnienia, lekkiego
    obrysu w barwie faktycznego kompletu reprezentacji, górnego okna portretu,
    stykającej się z nim belki nazwy i flagi oraz trzech zamkniętych w karcie
    zestawów podań, strzałów i obrony. Zmiennymi danych są wyłącznie portret,
    barwa akcentu, wartości, nazwa i flaga; HUD meczu pozostaje ukryty do
    pierwszego gwizdka.
  • W trakcie zapowiedzi kamera korzysta z całego ekranu i przez dokładnie
    sześć sekund wykonuje jeden ciągły obrót izometryczny o 360 stopni. Kąt
    jest ustawiany bezpośrednio dla każdej klatki, a kamera zaczyna z lekkim
    oddaleniem, płynnie wraca do standardowego zbliżenia i kończy obrót
    dokładnie w pierwotnym kadrze startowym przed rozsunięciem paneli.
  • Po obrocie karta gracza odrywa się po przekątnej w górę i lewo, a karta
    rywala w dół i prawo. Mechaniczny ruch z krótkim cofnięciem trwa 720 ms,
    podczas gdy przyciemnienie planszy zanika i odsłania gotową rozgrywkę.
  • Motyw Greg Eaton - Microprose Soccer Theme gra w menu i przez całą
    prezentację przedmeczową. Bezpośrednio po pierwszym gwizdku rozpoczyna się
    2,4-sekundowy equal-power crossfade do muzyki lokalnej reprezentacji;
    źródła kontynuują później własne łagodne zapętlenie, a brak utworu drużyny
    pozostawia motyw główny.

  Poprawki:
  • Portret zachowuje oryginalne proporcje, jest kotwiczony górną krawędzią do
    maski i przycinany wyłącznie od dołu, dlatego głowa gwiazdy pozostaje w
    całości widoczna, a między portretem i belką kraju nie powstaje przerwa.
  • Etykieta i wartość każdej statystyki korzystają dokładnie z prostokąta 350
    px odpowiadającego belce segmentów: tekst jest wyrównany do jej lewej i
    prawej krawędzi, nie nachodzi na wykres i nie wychodzi poza kartę.
  • Na czas prezentacji piłka leży dokładnie na fizycznym środku boiska; przy
    pierwszym gwizdku kontroler ustawia ją ponownie zgodnie z właściwym stanem
    meczu.
  • Nagłówki stron są rozjaśnione w obrębie barwy reprezentacji i mają
    kontrastowy jednopikselowy outline, więc pozostają czytelne na obracającym
    się boisku.
  • Segmenty umiejętności zaczynają się równo z lewą krawędzią tła wykresu,
    kończą na prawej bez bocznego paddingu i korzystają z dokładnie tego
    samego czerwono-pomarańczowo-limonkowo-turkusowego gradientu oraz koloru
    pustych pól co podgląd drużyny w menu głównym.

Dźwięki gwizdków i gola w meczu
-------------------------------
25.07.2026, 09:22

  • Mecz używa dostarczonych próbek first_blow, goal i final_blow odpowiednio
    przy rozpoczęciu, zdobyciu bramki i końcu spotkania. Długi końcowy gwizdek
    odtwarza się jednokrotnie po otwarciu widoku statystyk.

Portrety gwiazd reprezentacji w wyborze drużyny
-----------------------------------------------
25.07.2026, 09:15

  • Ekran wyboru drużyny pokazuje pełnopostaciowe, dopracowane portrety
    inspirowane gwiazdami Włoch, Hiszpanii, Anglii, Argentyny i Norwegii:
    odpowiednio Donnarummą, Lamine’em Yamalem, Kane’em, Messim i Haalandem.
    Każdy zachowuje charakterystyczną sylwetkę oraz barwy reprezentacji.
  • Portrety mają format 340×400 z przezroczystym tłem, spójny z pozostałymi
    kartami drużyn. Stroje są pozbawione logotypów producentów i sponsorów;
    użyto wyłącznie neutralnych detali reprezentacyjnych oraz herbów
    federacji.

Bezpośrednie decyzje X/O, zakładki L1/R1 i pomoc DualSense
----------------------------------------------------------
25.07.2026, 08:58

  • W panelu pojedynku X zawsze potwierdza wskazany cel, a kółko zawsze
    anuluje akcję. Stopka nie przejmuje już nawigacji kierunkowej, więc zmiana
    celu nie może jednocześnie zmienić decyzji między potwierdzeniem i
    anulowaniem.
  • Przyciski pojedynku pokazują animowane podpowiedzi X i kółka z
    dostarczonych par PNG wyłącznie na tvOS albo po rzeczywistym wykryciu
    podłączonego pada. Na Macu i innych platformach bez kontrolera przyciski
    pozostają czyste; podłączenie lub odłączenie pada podczas widocznego
    pojedynku przełącza ikony na żywo. Grafika zwolnionego przycisku
    przechodzi na krótko w wariant wciśnięty i zmniejsza się, po czym wraca do
    stanu spoczynkowego.
  • Panel STEROWANIE w opcjach ma tę samą wysokość i górną krawędź co PROFIL,
    DŹWIĘK I HAPTYKA, a jego zawartość dopasowuje się do platformy i
    podłączonych urządzeń. macOS oraz pozostałe platformy desktopowe bez pada
    pokazują rzeczywiste skróty myszy i klawiatury, urządzenia mobilne bez
    pada pokazują gesty dotykowe, a tvOS lub dowolna platforma z wykrytym
    padem pokazuje mapowanie ikonami DualSense. Podłączenie albo odłączenie
    pada podczas otwartych opcji przełącza pomoc od razu, bez mieszania
    instrukcji pada ze Spacją.
  • L1 i R1 emitują wspólne zdarzenie zmiany zakładki dla aktywnych ekranów
    menu. W STATYSTYKI I HISTORIA przełączają cyklicznie TABELA, STRZELCY,
    SIECIOWE i LOKALNE oraz przenoszą gradientowy focus na nową zakładkę.
    Animowane ikony po bokach paska są widoczne wyłącznie na tvOS albo po
    wykryciu podłączonego pada i znikają na żywo po jego odłączeniu.

  Poprawki:
  • Spacja podczas legalnej aktywacji wysyła tę samą strzeżoną komendę
    zakończenia aktywacji co przycisk HUD-u; nie działa podczas blokady
    wejścia, powtórki ani otwartego panelu modalnego.

Biały strój domowy Argentyny
----------------------------
25.07.2026, 08:45

  • Domowy komplet Argentyny ma białą bazę z błękitnymi pasami, a jego rodzina
    koloru to White. Włochy kontra Argentyna oraz mecze Argentyny z Marokiem,
    Belgią, Szwajcarią i Hiszpanią pozostawiają więc obu uczestników w
    strojach domowych; gość przechodzi na komplet wyjazdowy wyłącznie przy
    rzeczywistym konflikcie rodzin barw.
  • Strona meczu i historia spotkań używają tej samej definicji białego stroju
    Argentyny, dzięki czemu pokazują zestaw kolorów zgodny z planszą.
  • Zmieniono UUID builda rozgrywki, aby mecz sieciowy nie łączył klientów z
    odmiennym doborem strojów.

Wynik i dolny HUD powtórek bramek
---------------------------------
24.07.2026, 17:20

  Poprawki:
  • Archiwalna powtórka od pierwszej klatki pokazuje wynik już po odtwarzanym
    golu, zamiast wyniku checkpointu sprzed akcji; miga właściwie zmieniona
    cyfra także po zakończeniu animacji strzału.
  • Nakładka obrazu powtórki nie rysuje już czarnego paska nad dolnym HUD-em,
    więc nie zasłania tablicy wyniku.

Kwadrat wskazuje zawodnika bez aktywacji
----------------------------------------
24.07.2026, 17:14

  Poprawki:
  • Kwadrat na padzie nie wysyła już komendy wyboru zawodnika. Przesuwa
    wyłącznie kursor po dostępnych lokalnych zawodnikach w stałej kolejności,
    a dopiero X aktywuje wskazaną osobę.
  • Cykliczna podpowiedź pozostaje zablokowana po wydaniu punktów akcji, żeby
    nie sugerować niedostępnej zmiany zawodnika. Istniejący automatyczny wybór
    jest zachowany wyłącznie wtedy, gdy do aktywacji został dokładnie jeden
    zawodnik.

Domyślne celowanie strzału w najlepsze pole
-------------------------------------------
24.07.2026, 17:12

  • Wejście w akcję STRZAŁ od razu wybiera legalne pole bramki z najwyższą
    wyliczoną szansą na gola. Automatyczny wybór przechodzi przez tę samą
    ścieżkę co kliknięcie lub sterowanie padem, więc natychmiast pokazuje
    obrys celu, tor lotu, pojedynek, procent i aktywny przycisk potwierdzenia.
  • Przy identycznej szansie wybierane jest pole bliższe środkowi bramki, a
    dalszy remis rozstrzyga stała kolejność pól na linii, dzięki czemu cel
    pozostaje deterministyczny.

  Poprawki:
  • Przycisk Submit użyty do otwarcia PODANIA, STRZAŁU, LOBA albo ODBIORU nie
    może w tej samej klatce zatwierdzić nowo pokazanej akcji. Automatyczny cel
    strzału jest wyłącznie podpowiedzią; wykonanie każdej akcji dwuetapowej
    zawsze wymaga osobnego kliknięcia albo kolejnego naciśnięcia X.
    Zignorowany pierwszy Submit nie chowa już panelu pojedynku — karty obu
    zawodników, umiejętności i procent pozostają widoczne aż do właściwego
    potwierdzenia albo anulowania.
  • Po otwarciu pojedynku padem fokus od razu ląduje na przycisku
    potwierdzającym i pokazuje ten sam animowany gradientowy outline co
    pozostałe UI. POTWIERDŹ i ANULUJ mają własną, zamkniętą mapę nawigacji:
    każdy kierunek przełącza między nimi, bez uciekania fokusa do ukrytych
    akcji.

Najnowsze zmiany na początku changelogu strony
----------------------------------------------
24.07.2026, 13:09

  Poprawki:
  • Generator changelogu strony odwraca kolejność punktów w obrębie każdego
    dnia, więc zakładka POBIERZ pokazuje najnowsze wprowadzone zmiany na
    górze, zachowując porządek dni od najnowszego.

Muzyka surround i pozycjonowanie efektów meczu
----------------------------------------------
24.07.2026, 13:04

  • Muzyka meczu jest dekodowana jako szerokie źródło 360° przy słuchaczu,
    dzięki czemu w konfiguracji surround tvOS trafia także do tylnych satelit
    zamiast pozostawać wyłącznie z przodu.
  • Efekty kopnięć, strzałów, odbiorów, bramki i kontaktu ze słupkiem mają
    własne źródła 3D w punkcie akcji. Ich panorama, odległość i kanały
    surround wynikają teraz z położenia zawodnika lub piłki względem kamery.

  Poprawki:
  • Efekty 3D zachowują pełną głośność na całym boisku, także z wysoko
    położonej kamery izometrycznej i taktycznej na Macu; wcześniej
    logarytmiczny spadek głośności niemal je wyciszał.

Kamera taktyczna stale śledzi piłkę
-----------------------------------
24.07.2026, 13:03

  • Widok z góry kotwiczy się teraz na piłce niezależnie od wybranego
    zawodnika, grupy oczekującej na ruch i znacznika celowania. Po pionowym
    obrocie płynnie podąża za połową, na której znajduje się piłka.
  • Cel podania, strzału albo loba, który nie mieści się obok piłki,
    automatycznie poszerza kadr i przesuwa go tylko o tyle, by zachować w nim
    jednocześnie piłkę oraz znacznik celu; oddalenie nie przekracza widoku
    całego boiska. Przy wejściu w podanie widok z góry obejmuje od razu
    najdalszego legalnego odbiorcę, więc każdy znacznik pozostaje klikalny.
  • Zmieniono UUID builda rozgrywki, aby mecze sieciowe nie łączyły klientów z
    inną mechaniką prowadzenia kamery.

Czytelny błąd niedostępnego pokoju sieciowego
---------------------------------------------
24.07.2026, 12:00

  Poprawki:
  • Gdy gospodarz pokoju nie odpowiada, ekran gry sieciowej pokazuje krótką,
    zrozumiałą informację z podpowiedzią odświeżenia listy lub wyboru innego
    pokoju, zamiast technicznego komunikatu Netcode o wyczerpaniu prób
    połączenia.
  • Surowy powód rozłączenia pozostaje w logu diagnostycznym, a odrzucenia
    celowo opisane przez gospodarza, takie jak pełny pokój albo niezgodna
    wersja gry, nadal są przekazywane graczowi bez zmian.

Naturalne kierunki kursora i priorytet akcji pada
-------------------------------------------------
24.07.2026, 11:57

  • Menu akcji pada domyślnie podświetla legalny STRZAŁ, następnie legalny
    LOB, a dopiero przy braku obu korzysta z pierwszej pozostałej akcji,
    zazwyczaj PODANIE.

  Poprawki:
  • Kierunki kursora pada zależą od widoku i kierunku ataku. Wszystkie cztery
    ustawienia kamery izometrycznej mają osobne, jawne mapy D-pada i analoga
    zamiast mapy obracanej obliczeniowo. W domyślnej perspektywie góra
    prowadzi ku bramce przeciwnika, dół ku własnej, prawo na prawe skrzydło, a
    lewo na przeciwne. W drugim ustawieniu góra prowadzi na prawe skrzydło,
    dół na lewe, lewo do bramki rywala, a prawo do własnej; dwa pozostałe
    ustawienia są wpisanymi wprost dalszymi ćwierćobrotami. Top-down i 3D
    nadal wybierają naturalny krok według docelowej projekcji ekranowej, która
    nie zmienia się w trakcie animacji obrotu.

Zwarty panel statusu meczu sieciowego
-------------------------------------
24.07.2026, 11:26

  • Panel statusu meczu sieciowego pokazuje Online albo Rozłączono po prawej
    stronie tego samego wiersza co runda, aktywna reprezentacja i licznik
    ruchu. Informacja o tym, czyj jest ruch, pozostaje w drugim wierszu,
    dzięki czemu panel jest niższy.

Haptyka DualSense dla nawigacji, konstrukcji bramki i tvOS
----------------------------------------------------------
24.07.2026, 11:21

  • DualSense daje mocny, krótki impuls przy przejściu padem między
    kontrolkami UI (48%/32% silników przez 75 ms). Impuls jest wywoływany na
    przejściu gradientowego obramowania z niewidocznego do widocznego, więc
    jest zsynchronizowany z dokładnym momentem pojawienia się wizualnego
    focusa i nie zależy od kolejności aktualizacji trackera oraz EventSystemu.
  • Trafienie w słupek albo poprzeczkę uruchamia mocny, 0,2-sekundowy impuls
    obu silników dokładnie w chwili kontaktu piłki z konstrukcją bramki,
    równolegle z dźwiękiem odbicia.
  • Wibracje są obsługiwane przez pojedynczy komponent zarządzający czasem
    trwania i resetem silników; brak pada lub sprzęt bez silników pozostaje
    bezpiecznym no-opem, a zamknięcie sceny zawsze zatrzymuje aktywną
    wibrację.
  • W buildzie macOS oraz w edytorze Unity na Macu ten sam feedback trafia
    również do gładzika Force Touch: wejście kursorem na nową kontrolkę oraz
    nawigacja padem dają systemowy klik, a kontakt piłki ze słupkiem lub
    poprzeczką daje mocny wzór. AppKit jest wywoływany bezpośrednio przez
    runtime Objective-C, bez zależności od osobnego pluginu binarnego.
  • Na tvOS DualSense korzysta z Core Haptics związanego bezpośrednio z
    podłączonym kontrolerem, zamiast z zawodnej na tej platformie ogólnej
    komendy silników Unity. Krótki wzór odpowiada nawigacji, mocniejszy
    kontaktowi ze słupkiem lub poprzeczką, a test ustawień ma pełne dwie
    sekundy. Build tvOS deklaruje także wymagany profil rozszerzonego
    kontrolera.
  • Za każdym razem, gdy pad dostaje nowy wybór zawodnika — po powrocie
    sterowania od rywala albo po zakończeniu aktywacji, gdy ta sama drużyna
    zachowuje kolejny ruch — kursor przechodzi na zawodnika własnej drużyny
    najbliższego piłce, który nadal może się aktywować. Zawodnik z
    wykorzystaną aktywacją jest pomijany nawet wtedy, gdy nadal ma piłkę;
    zwykłe odznaczenie nie przestawia kursora. Podpowiedź nie uruchamia
    aktywacji ani akcji, a istniejący automatyczny wybór jedynego dostępnego
    zawodnika pozostaje bez zmian.
  • Publiczny stan lokalnej tury rozróżnia teraz rzeczywistą turę gracza od
    prezentowanej przez ten sam kontroler tury AI w meczu offline, dzięki
    czemu sterowanie padem i podpowiedź kursora wracają dokładnie po
    zakończeniu ruchu komputera.
  • Na iPadzie ekran OPCJE nie pokazuje ustawień wibracji ani siły wibracji,
    ponieważ tablet nie ma własnej haptyki dla tych kontrolek. Pozostałe
    ustawienia i obsługa pada pozostają bez zmian.
  • Eksport tvOS czyści przed kompilacją wyłącznie cache Burst dla iOS-Arm i
    tvOS-Arm. Zapobiega to przejęciu przez bibliotekę tvOS obiektów Mach-O
    skompilowanych dla iPadOS podczas pełnego buildu wieloplatformowego.
  • Ekran OPCJE zawiera teraz WIBRACJE (WŁ/WYŁ) i dziesięciostopniową SIŁĘ
    WIBRACJI. Oba ustawienia zapisują się lokalnie wraz z profilem; mnożnik
    jest stosowany do silników pada i do doboru wzoru Force Touch, a poziom 0
    albo WYŁ od razu zatrzymuje trwający impuls.
  • Wibracja focusa jest teraz wywoływana na przejściu gradientowego
    obramowania z niewidocznego do widocznego, a nie podczas wcześniejszego
    eventu wyboru UI. Eliminuje to zależność od kolejności aktualizacji
    EventSystemu i trackera urządzeń. Przełączenie WIBRACJE na WŁ uruchamia
    niezależny od mnożnika, dwusekundowy test obu silników pada z maksymalną
    mocą oraz najmocniejszy wzór Force Touch.

  Poprawki:
  • Gradientowy outline zaznaczonej kontrolki nie znika już na macOS ani po
    zbudowaniu kontrolki w runtime. W każdej klatce odczytuje faktyczne
    zaznaczenie EventSystemu, niezależnie sprawdza położenie kursora i
    utrzymuje ramkę ponad etykietą, warstwą hover oraz dekoracjami dodanymi
    później, zamiast polegać wyłącznie na callbackach i kolejności tworzenia
    dzieci.
  • Klik Force Touch przy przejściu kursorem na kolejną opcję jest wyzwalany
    przez tę samą krawędź widoczności co gradientowy outline, a AppKit
    wykonuje wzór w trybie DrawCompleted, synchronizując dotyk z narysowaniem
    kolejnej klatki UI. Usunięto nieskuteczny mostek .mm, którego symbol nie
    trafiał do gotowej aplikacji macOS.
  • Eksport tvOS linkuje teraz prawidłowy CoreHaptics.framework; Unity samo
    dopisuje rozszerzenie .framework, więc metadane pluginu przekazują
    wyłącznie nazwę CoreHaptics i nie tworzą błędnej ścieżki
    CoreHaptics.framework.framework.

Stabilne uruchamianie meczu na tvOS
-----------------------------------
24.07.2026, 11:21

  Poprawki:
  • Gość meczu sieciowego po odebraniu snapshotu oddaje sterowanie warstwie
    Netcode i dopiero w następnym frame buduje planszę, zawodników oraz HUD,
    zamiast wykonywać całą ciężką inicjalizację synchronicznie wewnątrz
    callbacku wiadomości.
  • Tymczasowa kamera i AudioListener ekranu oczekiwania gościa są usuwane
    przed utworzeniem kamery meczu, więc połączenie online nie pozostawia
    dwóch aktywnych kamer renderujących tę samą scenę.
  • Czysto wizualne elementy planszy, zawodników, piłki i otoczenia
    współdzielą wbudowane siatki bez tworzenia setek tymczasowych colliderów;
    fizyka zachowuje tylko collider murawy oraz jawne hitboxy zawodników i
    celów w bramce, co usuwa pik pamięci kończący proces tvOS przez jetsam.
  • Kamera meczu i pełnoekranowa tekstura powtórki na tvOS zachowują natywną
    rozdzielczość, ale nie tworzą 4× multisamplowanych buforów koloru i głębi,
    które na urządzeniu 4K powodowały kolejny duży pik pamięci GPU.
  • Produkcyjny scheme Xcode wyłącza automatyczne GPU Frame Capture oraz Metal
    GPU Validation, żeby uruchomienie przez debugger nie zatrzymywało kopii
    zasobów Metal i nie zmniejszało pamięci dostępnej grze na Apple TV.
  • tvOS nie próbuje tworzyć zapisu meczu pod niedozwolonym /match-logs, gdy
    system zwróci pusty katalog danych trwałych.
  • Produkcyjny build tvOS zachowuje typy colliderów tworzone wewnętrznie
    przez prymitywy Unity, więc wejście do meczu sieciowego nie generuje setek
    błędów brakujących klas pod presją pamięci.
  • Agresywne usuwanie nieużywanego kodu pozostaje włączone; przed
    strippingiem chronione są wyłącznie cztery konkretne typy colliderów
    wymagane przez generowaną w runtime planszę, zawodników i piłkę.

Ikona ulubionej reprezentacji na platformach Apple
--------------------------------------------------
24.07.2026, 11:06

  • Po zapisaniu ulubionej reprezentacji na iOS i tvOS ikona gry na ekranie
    głównym zmienia się na portret gwiazdy tej drużyny; wybór BRAK przywraca
    podstawową ikonę, a zapisany wybór jest synchronizowany również przy
    starcie gry.
  • Na macOS portret gwiazdy zastępuje ikonę gry w Docku na czas działania
    aplikacji i jest ponownie nakładany przy każdym uruchomieniu; systemowa
    ikona podpisanego pakietu w Finderze pozostaje bez zmian.
  • Eksport iOS tworzy komplet wymaganych rozmiarów 14 alternatywnych ikon, a
    eksport tvOS tworzy dla każdej drużyny dwuwarstwową ikonę z portretem na
    tle boiska i rejestruje warianty w projekcie Xcode.
  • Natywny mostek zmiany ikony jest dołączany do iOS i tvOS, obsługa Docka
    macOS korzysta bezpośrednio z systemowego AppKit, a build Windows
    zachowuje dotychczasową ikonę.

  Poprawki:
  • Generator ikon skaluje portrety na CPU zamiast przez niedostępny w
    automatycznym eksporcie bez grafiki RenderTexture, więc iOS oraz tvOS
    otrzymują właściwe obrazy zamiast jednolitych białych ikon; kontrola
    wariancji pikseli przerywa eksport, gdyby obraz ponownie nie został
    odczytany.

Produkcyjne i bezpieczne buildy wieloplatformowe
------------------------------------------------
24.07.2026, 11:00

  • Skrypt budowania udostępnia -h i --help z opisem składni, platform,
    wszystkich opcji oraz przykładami typowych uruchomień.
  • Automatyczne buildy zawsze wymuszają profil produkcyjny: bez Development
    Build, debuggera, profilerów, deep profiling, code coverage i buildowania
    samych skryptów; plik Player Log oraz stack trace’y zwykłych logów i
    ostrzeżeń są wyłączone, a błędy i wyjątki zachowują lekkie trace’y
    skryptowe potrzebne do diagnozy crashy.
  • Eksporty iOS i tvOS jawnie używają fizycznego Device SDK, kompilatora
    IL2CPP Release, wysokiego poziomu managed stripping oraz strippingu
    nieużywanego kodu silnika.
  • Współdzielone scheme iOS i tvOS uruchamiają i profilują konfigurację
    Release, a archiwizacja nadal generuje produkcyjne .dSYM potrzebne do
    symbolikacji crashy.

  Poprawki:
  • Eksport iPadOS i tvOS aktualizuje odwołania współdzielonych scheme po
    zmianie nazwy pakietu .xcodeproj, dzięki czemu Xcode rozpoznaje platformę
    projektu i ponownie pokazuje dostępne urządzenia docelowe.
  • Wygenerowane projekty jawnie wyłączają sandbox skryptów użytkownika
    wymagany przez fazę Unity IL2CPP, która zapisuje artefakty zarówno w
    DerivedData, jak i w katalogu eksportu.
  • Częściowe uruchomienie przez --only albo --skip czyści wyłącznie katalogi
    i paczki wybranych platform; przykładowo eksport tvOS nie usuwa już
    istniejących buildów macOS, Windows ani iPadOS.
  • Częściowy build zachowuje również lokalne metadane i changelog ostatniego
    pełnego wydania, a podsumowanie pokazuje tylko paczki utworzone w bieżącym
    uruchomieniu.

Podanie na całe boisko
----------------------
24.07.2026, 09:53

  • Każdy zawodnik z piłką może podać do dowolnego kolegi na boisku — nie ma
    już twardego limitu odległości podania, a jedynym ograniczeniem jest
    szansa powodzenia. Wcześniej zawodnik z pola miał zasięg 12 kratek i dalsi
    koledzy w ogóle nie byli podświetlani jako cel.
  • Szansa podania spada z odległością dwuetapowo: do MaxPassRange (12 kratek)
    tak jak wcześniej, od szansy podania krótkiego do szansy podania długiego,
    a powyżej tej odległości dalej opada aż do minimalnej szansy przy
    przekątnej boiska. MaxPassRange jest więc teraz odległością odniesienia
    dla krzywej szansy, a nie granicą legalności.
  • Bramkarz nie ma już osobnej reguły zasięgu — wykop bramkarza korzysta z
    tej samej krzywej co podanie z pola, a jego role penalty nadal obniża
    skuteczność.
  • Komputer nie zaczyna wyrzucać piłki na oślep: nadal odrzuca podania
    poniżej progu minimalnej szansy, więc bardzo długie zagrania wybiera tylko
    wtedy, gdy rzeczywiście mają sens.
  • Podbity GameplayBuildUuid, bo zmienia się mechanika rozgrywki wspólna dla
    hosta i gościa.

Piłka opada z siatki po golu
----------------------------
24.07.2026, 09:41

  • Po zdobyciu bramki piłka nie wisi już w siatce w miejscu trafienia: łapie
    ją siatka, po czym piłka opada na murawę wewnątrz bramki, odbija się dwa
    razy coraz niżej i tam zostaje do wznowienia gry.
  • Czas opadania zależy od wysokości trafienia — strzał w górny róg spada
    dłużej niż niskie wykończenie — a siatka odbija piłkę o kawałek z powrotem
    w stronę boiska, zamiast pozwolić jej zsunąć się pionowo po oczkach.
  • Powtórka gola nadal odtwarza sam lot do siatki, a po jej zakończeniu piłka
    wraca na ziemię w bramce, bo pozycja „na żywo” jest zapisywana już po
    opadnięciu.

Filtr CRT na powtórce bramki
----------------------------
24.07.2026, 09:40

  • Powtórka bramki jest wyświetlana przez filtr CRT: obraz kamery powtórki
    trafia do tekstury i jest malowany na pełnym kadrze przez shader
    TacticsFootball/CrtReplay. Efekt to wyłącznie kineskopowy obraz — linie
    skanowania, maska aperturowa RGB, aberracja chromatyczna, ziarno,
    migotanie i winieta. Geometria kadru zostaje nietknięta: żadnego wygięcia
    beczkowatego ani ramki kineskopu.
  • Kamera powtórki renderuje do RenderTexture o rozmiarze widoku (kadr kamery
    meczowej, więc pasek HUD nadal zostaje odsłonięty), a nakładka powtórki ma
    pod belką letterboxu pełnoekranowy RawImage z materiałem filtra. Tekstura
    jest tworzona przy wejściu w powtórkę i zwalniana przy wyjściu, więc
    zmiana rozdzielczości zawsze daje ostry obraz.
  • Linie skanowania są głównym elementem filtru: grube i wyraźne zamiast
    gęstych — jedna linia na siedem pikseli wysokości obrazu, siła 0,62 przy
    łagodniejszym wykładniku (_ScanlineSharpness 1,1), więc pasma są szerokie
    i mocno kontrastowe. Wiązanie gęstości z wysokością tekstury daje tę samą
    grubość linii na każdym ekranie. Po obrazie powoli spływa w dół pojedynczy
    przyciemniony pas rozsynchronizowanego kineskopu.
  • Doszły artefakty lo-fi psutego sygnału: pojedyncze linie od czasu do czasu
    urywają się w bok (utrata synchronizacji poziomej), obraz ciągnie za sobą
    przyciemnione echo w prawo (źle zakończony kabel kompozytowy), po
    pojedynczych liniach przelatują jasne smugi dropoutu taśmy, a kolor jest
    kwantowany do dwudziestu kilku poziomów, przez co gradienty murawy i nieba
    wyraźnie się schodkują. Wszystkie artefakty są losowane per linia
    skanowania i progowane, więc pojawiają się rzadko i nie zasłaniają akcji.
  • Ziarno, migotanie i spływający pas są napędzane z kodu
    (Time.unscaledTime), żeby zachowywały się tak samo na każdej platformie.
  • Gdy shader nie jest dostępny w buildzie, powtórka renderuje się
    bezpośrednio na ekran jak wcześniej, tylko z ostrzeżeniem w logu.

  Poprawki:
  • Pasek komentarza nie wystaje już spod belki letterboxu podczas powtórki.
    Ticker leży w kadrze kamery, tuż nad tablicą wyników, więc
    SetReplayIndicator chowa go na czas powtórki i przywraca wraz z
    pozostałymi elementami HUD-u, respektując ustawienie komentarza.

Kolejność akcji napastnika i wysokość panelu akcji
--------------------------------------------------
24.07.2026, 09:37

  • Napastnik ma na liście akcji STRZAŁ na pierwszym miejscu, przed PODANIE.
    Dla pozostałych formacji kolejność zostaje bez zmian (podanie, strzał,
    odbiór, lob, cofnij ruch, zakończ turę).
  • Panel akcji przy dokładnie czterech widocznych akcjach jest rozciągany do
    wysokości karty profilu zawodnika, a nadmiar wysokości rozkłada się równo
    między odstępy przycisków, więc oba bloki HUD kończą się na tej samej
    linii. Przy innej liczbie akcji panel nadal opina się ciasno wokół
    przycisków.

Strój wyjazdowy gościa na stronie statystyk
-------------------------------------------
24.07.2026, 09:35

  Poprawki:
  • Strona meczu i lista ostatnich spotkań kolorowały obie drużyny barwami
    stroju podstawowego, więc derby (obaj gracze tą samą reprezentacją) albo
    dwa zbliżone komplety dawały dwa identyczne kolory nie do rozróżnienia.
  • Strona meczu i tabela historii wybierają teraz strój gościa tą samą regułą
    co gra: przy tej samej reprezentacji albo przy wspólnej rodzinie barw
    (KitColorGroup) gość dostaje kolor stroju wyjazdowego, a gospodarz zostaje
    przy podstawowym.
  • Palety wyjazdowe wszystkich czternastu reprezentacji dopisane jako zmienne
    CSS --team-*-away, policzone z AwayKit(...).InterfaceColor.

Płaskie, studyjne oświetlenie boiska i zawodników
-------------------------------------------------
24.07.2026, 09:20

  • Scena meczowa jest oświetlona równomiernie, po studyjnemu: główną porcję
    światła daje wysoki, neutralny ambient (RenderSettings.ambientLight), więc
    zawodnicy i murawa mają tę samą jasność niezależnie od pozycji na boisku i
    od tego, w którą stronę są zwróceni.
  • Cztery narożne reflektory zastąpione czterema bezcieniowymi światłami
    kierunkowymi (prawe, lewe, tylne i odbicie od dołu). Kierunkowe nie mają
    wygaszania z odległością, więc znikły jaśniejsze plamy przy masztach i
    ciemniejsze środki boiska.
  • Główne światło kierunkowe (intensywność 1,15 zamiast 1,45) modeluje bryłę
    i jest jedynym źródłem cienia. Siła cienia 0,9 dotyczy wyłącznie wkładu
    tego światła, więc przy wysokim ambiencie cień zawodnika jest wyraźnie
    widoczny na murawie, a mimo to nie robi się z niego ciemna dziura.
  • Poziomy dobrane tak, żeby cień nie utonął w rozświetlonej scenie: ambient
    0,40, wypełniacze boczne i tylny 0,22–0,24, a odbicie od dołu tylko 0,06 —
    mocniejsze podświetlenie spodu figur kasowało cień kontaktowy.
  • Materiały zawodników dostają śladowy własny wypełniacz (0,16 zamiast
    0,65), bo jasny ambient sam wystarcza; ciemne stroje i karnacje nadal się
    nie zlewają, a białe koszulki nie prześwietlają się.

Celność podań i jednolity zestaw statystyk meczu
------------------------------------------------
24.07.2026, 09:17

  • Raport meczu pokazuje dodatkowy wiersz CELNOŚĆ PODAŃ zaraz pod PODANIA
    NIECELNE: procent podań celnych względem wszystkich prób (celne +
    niecelne), zaokrąglony do pełnych procent, 0% przy braku podań.
  • Ekran meczu w grze i strona meczu w lobby mają ten sam zestaw wierszy w
    tej samej kolejności: do raportu w grze doszła SKUTECZNOŚĆ ODBIORÓW, a na
    stronie ODBIORY: PRÓBY nazywa się teraz PRÓBY ODBIORU. Obie strony liczą
    procenty tak samo.
  • Tabela statystyk mieści teraz dwanaście wierszy w tej samej ramce dzięki
    mniejszemu odstępowi między wierszami.

Celność podań w statystykach meczu
----------------------------------
24.07.2026, 09:17

  • Raport meczu pokazuje dodatkowy wiersz CELNOŚĆ PODAŃ zaraz pod PODANIA
    NIECELNE: procent podań celnych względem wszystkich prób (celne +
    niecelne), zaokrąglony do pełnych procent, 0% przy braku podań.
  • Tabela statystyk mieści teraz jedenaście wierszy w tej samej ramce dzięki
    nieco mniejszemu odstępowi między wierszami.

Czytelniejsze procenty przy celowaniu do bramki
-----------------------------------------------
24.07.2026, 09:00

  • Procenty na kolumnach celowania są wyraźnie większe (osobna skala tekstu
    tylko dla bramki, 1,15× względem znaczników na murawie, dobrana tak, by
    liczba nie była szersza niż tarcza, którą opisuje), więc dają się odczytać
    z drugiego końca boiska i nie nachodzą na siebie.
  • Liczby stoją teraz na jednej wysokości, w szczelinie między dwoma rzędami
    tarcz, w połowie wysokości bramki, zamiast wspinać się nad poprzeczkę.
    Etykieta jest odsunięta przed tarcze po stronie boiska, więc nie chowa się
    w siatce ani w tarczy.
  • Procenty na wszystkich znacznikach (murawa, odbiór, bramka) są nieco
    większe i mają równomierny ciemny obrys zamiast pojedynczego cienia z
    jednej strony.

  Poprawki:
  • Przy niskim ustawieniu kamery cień etykiety wysuwał się spod cyfr i liczba
    wyglądała na w połowie czarną. Obrys z czterech kopii trzyma biały tekst w
    jednolitym kolorze pod każdym kątem.
  • Ciemne kopie obrysu potrafiły narysować się na białej wartości, bo
    wszystkie leżą w tym samym miejscu w kolejce przezroczystej i o kolejności
    decydowała odległość. Wartość ma teraz sortingOrder 1, a obrys 0, więc
    biel zawsze jest na wierzchu.
  • Etykiety procentów są jawnie odcięte od oświetlenia sceny: bez rzucania i
    odbierania cieni, bez light probe'ów i reflection probe'ów, więc kolor nie
    zależy już od tego, jak oświetlona jest bramka.

Uderzenie, prędkość i tor lotu strzałów oraz podań
--------------------------------------------------
24.07.2026, 08:55

  • Piłka rusza teraz dopiero pod koniec animacji kopnięcia: PlayKick
    przyjmuje moment wypuszczenia piłki jako parametr, strzały i loby
    zwalniają ją przy 95% zamachu (PlayerView.ShotReleaseFraction), a podania
    przy 88% (PlayerView.PassReleaseFraction). Wolej elitarnego strzelca ma
    własny, wcześniejszy moment kontaktu i pozostaje bez zmian.
  • Czas lotu strzału nie jest już stały (PassAnimDuration).
    GetShotFlightDuration wylicza prędkość z umiejętności strzału (11,5–24
    pola/s), doładowuje ją dystansem (dalekie uderzenia lecą mocniej niż
    dobitki z pola bramkowego), tłumi przy ostrym kącie do bramki i rozsiewa o
    ±6% stabilnym hashem strzelca i celu. Strzał broniony przez bramkarza
    mieści się w węższym zakresie, żeby lot zgadzał się z animacją
    interwencji.
  • ApplyShotSpin skaluje rotację umiejętnościami: podkręcenie boczne zależy
    od strzału i kontroli piłki, obrót wzdłużny od samego strzału. Prędkość i
    rotacja są wyłącznie warstwą wizualną — o wyniku decyduje jak dotąd
    deterministyczny rdzeń.
  • GetShotCurve rozróżnia trzy przypadki. Z otwartej gry, jak dotąd, kręcą
    tylko dobrzy strzelcy z dystansu. Z ostrego kąta (do 2,6 pola od linii
    końcowej) każdy strzał jest zakrzywiony: wychodzi w głąb boiska i dokręca
    do bramki, tym mocniej, im ciaśniejszy kąt. Z pola sąsiadującego z linią
    bramkową (do 1,6 pola, PointBlankGoalDepth) piłka nie kręci wcale — nie ma
    na to miejsca, więc leci prosto tam, gdzie została uderzona. Taki strzał
    nie jest też tłumiony jak plasowany: przy zerowym dystansie do linii nie
    ma czasu na plasowanie.
  • Każdy łuk jest przycinany do boiska. TrimCurveToPitch (strzały) i
    TrimPassCurveToPitch (podania, obie osie) próbkują tor i ograniczają
    wygięcie tak, by nie zbliżyło się do linii bocznej bliżej niż
    BoardView.ShotLaneMargin, a BallView.SetPitchLaneBounds dokłada twardy
    limit w samych funkcjach toru lotu, wspólny dla lotu piłki, linii
    celowania i powtórki.
  • Podania mają teraz własny, zróżnicowany tor lotu opisany przez
    GetPassFlightStyle. Prędkość wynika z podania (7,5–14,5 pola/s), rośnie z
    dystansem, spada dla piłek podcinanych i jest rozsiewana o ±6% stabilnym
    hashem; czas lotu ma osobne widełki dla podania po ziemi i dla loba.
  • GetPassCurve daje podaniom łuk mierzony w poprzek kierunku lotu
    (BallView.EvaluatePassPosition), więc działa w każdą stronę boiska, a nie
    tylko wzdłuż osi bramek. Zakręca tym mocniej, im lepszy podający i im
    dłuższe podanie, i wygina piłkę na przeciwną stronę niż najbliższy obrońca
    stojący w linii podania. Podający poniżej 0,45 umiejętności gra prosto,
    tak samo jak każde podanie krótsze niż 2,5 pola.
  • Wysokość łuku loba zależy od umiejętności podania (arcScale w
    AnimatePassTo i ShowPassLine), więc dobry podający naprawdę podcina piłkę,
    a słaby posyła ją płasko.
  • ApplyPassSpin nadaje rotację także podaniom: podkręcenie boczne z podania
    i kontroli piłki, obrót wzdłużny z samego podania, a podcinane loby
    częściej dostają rotację wsteczną. AnimatePassTo nie zeruje już rotacji
    samo z siebie — ustawia ją strona wywołująca, jak przy strzałach.
  • Linia celowania podania rysuje ten sam łuk i tę samą wysokość, którą
    poleci piłka.
  • Powtórka bramki odtwarza nowe wyczucie uderzenia: kopnięcie zaczyna się
    przed lotem piłki, tak jak na żywo.
  • UUID buildu klienta podbity na aeaa3a2a-b269-4bf3-ac82-1bf63cfbb3a8, bo
    zmieniają się animacje strzału i podania.

  Poprawki:
  • Strzał z narożnika nie wylatuje już poza boisko i nie wpada do bramki
    przez boczną siatkę. Wcześniej łuk był kierowany na tę stronę bramki, w
    którą celował strzelec, więc uderzenie z okolic linii końcowej wyginało
    piłkę na zewnątrz pola gry.

Changelog dla graczy grupowany po dniach, z podziałem na nowości i poprawki
---------------------------------------------------------------------------
24.07.2026, 08:41

  • CHANGELOG-PLAYERS.md ma teraz jeden nagłówek na dzień (## YYYY-MM-DD —
    tytuł dnia), bez godzin. Punkty z danego dnia są rozdzielone na sekcje
    Nowości i zmiany oraz Poprawki, w każdej chronologicznie od
    najwcześniejszej do najpóźniejszej; dni pozostają od najnowszego na górze.
  • Istniejące wpisy przepisane do nowego układu — trzy dni zamiast osobnego
    wpisu na każde zadanie.
  • Tools/make-web-changelog.py przyjmuje nagłówki bez godziny (brakująca
    godzina liczy się jako 00:00 przy sortowaniu) i rozpoznaje nagłówki
    sekcji, wystawiając osobne pola items i fixes w changelog.json.
  • Strona statystyk (zakładka POBIERZ) pokazuje w karcie dnia dwie grupy —
    „NOWOŚCI I ZMIANY" i „POPRAWKI" — a grupa bez punktów w ogóle się nie
    renderuje. ChangelogEntry ma odpowiadające pole Fixes.
  • Instrukcje projektu wymagają teraz wyraźnego rozdzielenia zmian od
    poprawek w obu changelogach: w CHANGELOG-DEV.md przez sekcje Changed i
    Fixed, w CHANGELOG-PLAYERS.md przez sekcje dnia.
  • Instrukcje projektu mówią wprost, że kodu Go ani C# nie buduje się i nie
    uruchamia lokalnie: serwer odpala użytkownik, a za C#/Mono odpowiada
    Unity.

  Poprawki:
  • Punkty w CHANGELOG-PLAYERS.md przypisane do właściwych dni według dat
    odpowiadających wpisów w CHANGELOG-DEV.md: monit o dostępnej aktualizacji
    figurował podwójnie — pod 22.07 i 23.07 — a należy wyłącznie do 22.07,
    komentarz rozpoczęcia meczu stoi teraz przed motywami muzycznymi, a
    większe procenty przy celowaniu przed płaskim oświetleniem, zgodnie z
    kolejnością godzin.

Handel Gothic jako font interfejsu, Rocabe tylko w tytule gry
-------------------------------------------------------------
24.07.2026, 07:58

  • Font eksponowany interfejsu (UiSupport.DisplayFont) to teraz Handel Gothic
    Regular. Obejmuje to wszystkie ekrany budowane w czasie działania: menu
    główne, opcje, multiplayer, statystyki, HUD meczu, raport meczowy oraz
    etykiety przycisków retro.
  • Rocabe został wydzielony do osobnego UiSupport.TitleFont z pomocnikiem
    ApplyTitleFont, używanego wyłącznie przez napis „TACTICAL FOOTBALL” w menu
    głównym.
  • Handel Gothic zawiera pełny alfabet polski, więc etykiety interfejsu nie
    spadają już na awaryjny JetBrains Mono z powodu brakujących znaków
    diakrytycznych.
  • Plik Handel Gothic Regular.ttf ma stały .meta z ustawieniami importu
    takimi jak pozostałe fonty, żeby GUID był ten sam na każdej maszynie i w
    każdym buildzie.

Komentarz meczowy pojawia się dopiero w chwili rozstrzygnięcia
--------------------------------------------------------------
24.07.2026, 07:49

  • Komentarz do podania, strzału, loba i odbioru nie zdradza już wyniku z
    wyprzedzeniem. Linia jest kolejkowana w MatchController i pokazywana
    dopiero wtedy, gdy rozstrzygnięcie widać na boisku: dla strzału po dolocie
    piłki (bramkarz zdążył zareagować), dla podania po wylądowaniu piłki, dla
    odbioru po zakończeniu animacji starcia. Dotyczy zarówno akcji gracza, jak
    i komputera.
  • MatchController ma wspólną warstwę komentarza: QueueMatchEvent wstrzymuje
    linię znającą wynik, FlushMatchEvent wypuszcza ją w momencie
    rozstrzygnięcia, a ShowMatchEvent pokazuje od razu linie, które nic nie
    zdradzają (ruch, koniec aktywacji, runda, koniec meczu). Kolejkowana linia
    nigdy nie ginie — każde kolejne zdarzenie najpierw opróżnia kolejkę.
  • Po zdobyciu bramki cały pasek komentarza miga w rytm banera GOOOL:
    dziesięć razy co 0,14 s zamienia kolory listwy i tekstu miejscami. Klatka
    odwrócona ma własne formatowanie nazwisk, dobrane do zamienionego tła,
    więc nazwiska pozostają czytelne. Linia, która trafi na pasek w trakcie
    migania, najpierw przywraca kolory bazowe, żeby nie przejąć odwróconej
    klatki na stałe.

Warstwowe ikony aplikacji dla Apple TV
--------------------------------------
23.07.2026, 20:09

  • tvOS korzysta teraz z kompletnego, dwuwarstwowego zestawu ikon aplikacji w
    rozdzielczościach 1280×768, 800×480 i 400×240. Tło stanowi panoramiczne,
    pikselowe boisko w palecie oryginalnej ikony, a przednia warstwa zachowuje
    znak z piłkarzem, bramkarzem i napisem „TACTICAL FOOTBALL” na
    przezroczystym płótnie, dzięki czemu systemowy efekt parallax działa
    prawidłowo. Znak zajmuje 78% wysokości kafelka, więc ma bezpieczny
    margines podczas systemowego powiększenia i wychylenia ikony.
  • Top Shelf ma własne, panoramiczne grafiki 1920×720, 3840×1440, 2320×720 i
    4640×1440 zamiast automatycznie rozciąganej przez Unity ikony aplikacji.
    Szeroki znak zachowuje dotychczasowy układ, ale zajmuje 80% banera i jest
    otoczony równym marginesem z pikselowego boiska.
  • Wszystkie trzy sloty ikon i cztery sloty Top Shelf w ustawieniach builda
    wskazują tekstury o dokładnie wymaganych wymiarach; walidator Unity
    rozpoznaje oba zestawy jako kompletne (App Icons 3/3, Top Shelf Icons 4/4)
    i nie zgłasza już braku drugiej warstwy.

Klik w gracza otwiera jego historię spotkań
-------------------------------------------
23.07.2026, 19:20

  Poprawki:
  • Kliknięcie nicku w tabeli na stronie statystyk lobby nie pokazywało już
    historii spotkań tego gracza. Odnośnik przeładowywał stronę z ?player=…,
    ale zachowywał zakotwiczenie #ranking, więc po wczytaniu nadal była
    widoczna tabela ligowa, a odfiltrowany (już wyrenderowany po stronie
    serwera) panel historii pozostawał ukryty. Odnośnik prowadzi teraz do
    #history, więc od razu widać spotkania danego gracza.
  • Link „← pokaż wszystkie spotkania” zostaje na zakładce historii
    (?#history) zamiast wracać na tabelę ligową.

Sterowanie padem DualSense i bezpieczna nawigacja na Apple TV
-------------------------------------------------------------
23.07.2026, 19:10

  • Pad jest teraz trzecią, równoległą metodą sterowania obok myszki i dotyku.
    Żadna z dotychczasowych ścieżek nie została zastąpiona ani wyłączona —
    wszystkie trzy kończą się w tych samych publicznych komendach
    MatchController.
  • MatchController wystawia wspólną warstwę komend: SelectTile, SelectPlayer,
    ConfirmAction, CancelAction, UndoMove, SelectNextTarget,
    SelectPreviousTarget oraz stan CurrentContext, CursorAnchor,
    AcceptsCameraInput. Kliknięcie myszką i tapnięcie przechodzą teraz przez
    te same metody, więc żadne urządzenie nie ma własnej logiki rozgrywki.
  • GameInputActions buduje w kodzie zasób Input Systemu z trzema schematami
    sterowania (Gamepad, Keyboard&Mouse, Touch) i jednym zestawem akcji:
    Navigate, Submit, Cancel, CyclePlayer, Pause, CycleCameraView, CameraLeft,
    CameraRight, CameraZoomIn, CameraZoomOut, NextTarget, PreviousTarget.
    Schematy nie są wyłączne — żadne urządzenie nie blokuje pozostałych.
  • Bindingi pada: X = Submit, O = Cancel, □ = CyclePlayer, △ =
    CycleCameraView, Options = Pause, L1/R1 = obrót kamery o krok, L2/R2 =
    zmiana poziomu zoomu, D-pad i lewy analog = Navigate, lewo/prawo dodatkowo
    jako PreviousTarget/NextTarget.
  • MatchGamepadInput tłumaczy naciśnięcia na komendy w trzech kontekstach:
    kursor po polach siatki, fokus w istniejącej kolumnie akcji i fokus w
    panelu modalnym. Nie ma swobodnego kursora ekranowego ani swobodnej kamery
    — ruch po siatce jest polem po polu, a pojedyncze wychylenie analoga daje
    jeden krok (powtarzanie startuje dopiero po 0,4 s).
  • Kierunki kursora są przeliczane względem obrotu kamery, więc „w górę”
    zawsze znaczy „w głąb boiska”, niezależnie od tego, w którym z czterech
    ustawień stoi kamera.
  • W trybie celowania pad nie używa kursora: lewo/prawo przechodzi po
    deterministycznie uporządkowanych celach — odbiorcy podania według kąta
    wokół podającego, a pola w bramce według pozycji na linii bramkowej
    przeliczonej na aktualną oś ekranu. Niezaznaczony jeszcze cel strzału
    zaczyna logicznie od środka bramki, więc pierwsze wychylenie od razu
    wybiera punkt po wskazanej stronie. Wybrany cel jest podświetlany
    dokładnie tak jak po kliknięciu, bo używa tych samych wywołań.
  • X na własnym, zaznaczonym zawodniku otwiera istniejące menu akcji i
    przenosi tam fokus. Po zakończeniu animacji ruchu fokus zawsze ląduje na
    pierwszej dostępnej akcji (dla zawodnika z piłką zwykle PODANIE) i nie
    przywraca ostatnio używanego przycisku. O w tym stanie natychmiast
    wywołuje tę samą komendę UndoMove co widoczny przycisk COFNIJ RUCH; gdy
    ruchu nie można cofnąć, wraca zwyczajnie na boisko. Naciśnięcie X na
    przycisku akcji obsługuje EventSystem, więc pad uruchamia dokładnie tę
    samą metodę co kliknięcie — nie powstały żadne osobne panele dla pada.
  • □ cyklicznie wybiera kolejnych lokalnych zawodników, którzy mogą jeszcze
    rozpocząć aktywację w bieżącej rundzie. Wybór idzie deterministycznie po
    identyfikatorach i korzysta ze zwykłej komendy SelectPlayer; po wydaniu
    punktów akcji zmiana zawodnika pozostaje zablokowana zgodnie z
    dotychczasowymi regułami.
  • Rozwijane menu HUD pełni rolę menu pauzy: GameHud wystawia OpenPauseMenu,
    ClosePauseMenu, TogglePauseMenu, CloseTopModal oraz rozpoznaje aktywny
    panel modalny (rozłączenie, raport pomeczowy, potwierdzenie zakończenia
    meczu, menu). Options otwiera i zamyka to samo menu co przycisk MENU.
  • CameraController dostał RotateCameraStep i ChangeZoomStep — nazwane
    wejścia dla kroku obrotu i kroku zoomu, wspólne dla HUD, klawiszy Q/E i
    pada. Kamera nadal działa wyłącznie skokowo, między ustalonymi pozycjami.
  • Trójkąt DualSense wywołuje tę samą komendę zmiany perspektywy co klawisz C
    i kontrolki HUD. Każde naciśnięcie przechodzi po wspólnym stanie kamery w
    pętli: izometryczna → 3D zza ramienia → top-down → izometryczna; etykiety
    i zaznaczenie przycisków HUD pozostają zsynchronizowane.
  • InputDeviceTracker rozpoznaje ostatnio używane urządzenie i przy przejściu
    na myszkę zdejmuje fokus pada, żeby nie przeszkadzał w klikaniu; przy
    powrocie na pad fokus wraca na ostatnio używany, sensowny element panelu.
    Pola tekstowe są wyjątkiem i zachowują fokus, żeby dało się w nich pisać.
    Przełączanie jest automatyczne, bez trybu wybieranego ręcznie.
  • RetroButtonHover obsługuje teraz również fokus klawiatury i pada
    (ISelectHandler/IDeselectHandler), mocniejszą poświatą niż zwykły najazd
    kursorem. Dodatkowo kontrolka aktywna padem albo wskazana kursorem myszy —
    przycisk lub pole tekstowe — dostaje tę samą jasną, czteroczęściową ramkę
    wysuniętą poza jej obrys. Ramka używa dokładnie palety i przesuwania
    gradientu CopperRail z menu głównego, zamyka cykl w 3 sekundy i lekko
    pulsuje jasnością, dzięki czemu ruch widać od razu. Jej grubość wynosi
    3,5% krótszego boku kontrolki (z ograniczeniem 2–6 jednostek), więc małe
    przełączniki mają delikatniejszy obrys od dużych przycisków. Ramka wygasza
    się po utracie focusa lub zejściu kursora i nie przechwytuje wejścia.
  • BoardView rysuje kursor pada jako pulsujące narożniki wokół pola w kolorze
    rzeczywistego kompletu strojów lokalnej reprezentacji, także wyjazdowego.
    Jest celowo inny niż znacznik zaznaczenia i niż pola ruchu: mówi „tu
    wskazuje analog”, a nie „to jest wybrane”. Kursor pojawia się tylko wtedy,
    gdy aktywny jest pad i trwa tura gracza.
  • Menu główne ma jawną mapę nawigacji pada obejmującą strzałki obu
    reprezentacji, przyciski rozpoczęcia meczu i gry sieciowej oraz dolny rząd
    statystyk, opcji i wyjścia. Początkowy fokus pada ląduje na ROZPOCZNIJ
    MECZ, a ekran sieciowy otwiera się z fokusem na ODŚWIEŻ LISTĘ.
  • Ekrany menu korzystają ze stosu zakresów modalnych: fokus nie może przejść
    do kontrolek pod aktywną nakładką, a po zamknięciu ekran oddaje fokus
    dokładnie kontrolce, która go otworzyła. O jest globalną akcją „wstecz” w
    całej aplikacji: wykonuje tę samą operację co widoczny przycisk WRÓĆ,
    ANULUJ albo WRÓĆ DO MENU, zawsze o jeden poziom; na głównym ekranie
    pozostaje bezczynny.
  • Każdy otwierany ekran menu buduje i na bieżąco odświeża jawną,
    czterokierunkową mapę nawigacji na podstawie rzeczywistego położenia
    aktywnych kontrolek. Obejmuje ona przyciski, dynamiczne wiersze i pola
    tekstowe, więc D-pad oraz lewy analog prowadzą przewidywalnie po całym UI
    mimo zmian zawartości panelu. Pola tekstowe mają własną złotą ramkę
    focusa.

  Poprawki:
  • Pad nie działał na tvOS w menu głównym. InputDeviceTracker nadawał fokus
    wyłącznie w momencie przełączenia urządzenia, a na platformie bez myszki
    takie przełączenie może nigdy nie nastąpić — po wejściu do sceny nic nie
    było zaznaczone, więc Navigate i Submit nie miały na czym zadziałać. Fokus
    jest teraz odzyskiwany na bieżąco (co 0,25 s), zawsze gdy pad jest
    aktywny, a zaznaczenia brak.
  • Na maszynie bez myszki, ale z podłączonym padem, sterowanie startuje od
    razu w trybie pada, więc menu ma fokus od pierwszej klatki i nie trzeba
    „budzić” pada wciśnięciem, które nic nie robi. Tam, gdzie jest myszka,
    start pozostaje bez zmian.
  • Na tvOS dotknięcia powierzchni pilota nie są już traktowane jak wejście
    wskaźnikowe. Apple TV nie ma kursora na ekranie, a takie dotknięcia
    zdejmowały padowi fokus w trakcie nawigacji po menu. Na iPadOS dotyk
    działa jak dotąd.
  • O na DualSense nie działało wcześniej jako spójne „wstecz”: w ekranie gry
    sieciowej mogło zamknąć aplikację, ekran wymaganej aktualizacji pomijał
    przeglądarkę pokojów, a raport pomeczowy i ekran rozłączenia ignorowały
    je. Globalna akcja Cancel kieruje teraz O do najwyższego aktywnego ekranu
    i wykonuje jego widoczną akcję powrotu. Na tvOS blokada systemowego
    wyjścia jest wymuszana przed sceną, podczas działania oraz po każdym
    wznowieniu aplikacji, a Canvas meczu pochłania równoległy event Cancel
    modułu UI po wykonaniu kontekstowej akcji przez MatchGamepadInput.
    Aplikację można zamknąć wyłącznie jawnym przyciskiem WYJDŹ Z GRY.
  • Po powrocie do aplikacji na Apple TV zaznaczenie mogło pozostać logicznie
    ustawione, ale bez widocznego i działającego fokusa. Wznowienie aplikacji
    ponownie osadza aktywną kontrolkę pada w bieżącym ekranie.
  • Po ukryciu panelu albo dynamicznej kontrolki EventSystem mógł nadal
    przechowywać nieaktywne zaznaczenie. Wyglądało to jak całkowicie martwy
    pad, ponieważ focus formalnie nie był pusty, ale nie przyjmował Navigate
    ani Submit. Tracker wykrywa teraz również nieużywalny focus i od razu
    przenosi go do aktywnego zakresu.
  • Automatyczna nawigacja Unity potrafiła zamknąć focus na dolnym przycisku
    ekranu opcji i pomijała pola pseudonimu lub nazwy pokoju. Przestrzenna
    mapa obejmuje teraz także InputField, więc można dojść do pola z pada i
    uruchomić edycję.
  • Po wejściu do pola tekstowego jego aktywny edytor przejmował kierunki
    pada, przez co nie dało się już przejść do pozostałych kontrolek. O jest
    obsługiwane najpierw przez samo pole: kończy edycję, zamyka klawiaturę
    ekranową i przenosi focus do pierwszej sąsiedniej kontrolki niebędącej
    kolejnym polem tekstowym, bez zamykania całego ekranu.
  • Pierwszy, 24-sekundowy ruch gradientu ramki pada był na krótkich
    krawędziach praktycznie nieodróżnialny od statycznej grafiki. Ośmiokrotnie
    szybszy przepływ palety (pełny cykl w 3 sekundy), subtelny puls jasności i
    grubość dopasowana do rozmiaru kontrolki dają teraz jednoznaczną animację
    bez przytłaczania małych przycisków.
  • Kierunki wyboru punktu strzału były powiązane ze stałą współrzędną boiska.
    Przy domyślnym ustawieniu kamery rosnąca pozycja na linii bramkowej
    biegnie na ekranie w lewo, dlatego prawy kierunek pada przesuwał
    zaznaczenie wizualnie w lewo. Krok jest teraz odwracany zależnie od
    aktualnej osi kamery, także po jej obróceniu lub zmianie perspektywy.
  • Automatyczny focus menu akcji po ruchu był ustawiany w callbacku
    zakończenia animacji, po czym znikał jeszcze w tej samej klatce: główna
    pętla wejścia widziała przejście kontekstu Blocked → Selecting i
    wykonywała ogólne czyszczenie focusa. Callback zapamiętuje teraz, że ruch
    został wydany padem, oraz aktualizuje migawkę kontekstu po wybraniu
    pierwszej akcji, więc następna aktualizacja nie usuwa PODANIE.

Wspólne kolumny tabeli w grze i w lobby oraz tabela strzelców
-------------------------------------------------------------
23.07.2026, 19:09

  • Tabela w grze ma teraz dokładnie ten sam zestaw kolumn co widok webowy
    lobby: LP · GRACZ · M · Z · R · P · BZ · BS · +/- · PKT. Brakującą różnicę
    bramek dodano po stronie gry, bo to widok lobby był pełniejszy.
  • Doszła tabela najlepszych strzelców, liczona per zawodnik, a nie per
    konto: gole i asysty tego samego piłkarza sumują się niezależnie od tego,
    kto w danym meczu prowadził jego reprezentację. Kolumny: LP · ZAWODNIK ·
    REPREZENTACJA · MECZE · ASYSTY · GOLE, gdzie MECZE to liczba meczów z jego
    udziałem w bramce (gol albo asysta).
  • Strzelcy są dostępni w obu miejscach: jako zakładka STRZELCY na ekranie
    statystyk w grze (ekran ma teraz cztery zakładki: TABELA, STRZELCY,
    SIECIOWE, LOKALNE) i jako zakładka STRZELCY na stronie statystyk lobby.
  • Nazwisko i reprezentacja strzelca są kolorowane strojem jego
    reprezentacji, tak samo w grze i na stronie; lider tabeli strzelców
    zachowuje złoty kolor, jak lider tabeli ligowej.
  • Serwer wystawia GET /v1/stats/scorers, agregując tabelę strzelców z tabeli
    goals złączonej z matches — reprezentacja strzelca bierze się ze strony,
    po której padł gol. Nie doszedł żaden nowy zapis w bazie: to zapytanie po
    istniejących danych, więc historyczne mecze też się liczą.
  • Skrótowe nagłówki kolumn na stronie statystyk (LP, M, Z, R, P, BZ, BS,
    +/-, PKT, a w tabeli strzelców LP, MECZE, ASYSTY, GOLE) są opakowane w
    <abbr> z rozwinięciem w dymku i kropkowanym podkreśleniem, żeby było
    widać, że podpowiedź istnieje.
  • Przełączanie zakładek na ekranie statystyk w grze opiera się teraz na
    jednym stanie StatsTab zamiast pary flag logicznych, a przyciski zakładek
    są węższe, żeby cztery zmieściły się w tym samym pasie co wcześniej trzy.
  • ServerProtocolUUID podbite po obu stronach, bo gra odpytuje endpoint,
    którego starszy serwer nie zna.

Derby w trybie sieciowym: obaj gracze mogą wybrać tę samą drużynę
-----------------------------------------------------------------
23.07.2026, 19:08

  • W trybie sieciowym obaj gracze mogą wybrać tę samą reprezentację.
    Gospodarz gra wtedy w pierwszym komplecie strojów, a gość w drugim
    (wyjazdowym).
  • NationalTeams.KitsForMatch traktuje derby wprost: przy identycznych
    reprezentacjach gość dostaje AwayKit, tak samo jak przy zbieżnej rodzinie
    kolorów. Reguła obowiązuje wszędzie, gdzie liczone są stroje meczu —
    plansza, zawodnicy, HUD, raport pomeczowy i ekran statystyk.
  • Zatwierdzanie połączenia po stronie gospodarza
    (NetworkSession.ApproveConnection) nie odrzuca już gościa za wybór drużyny
    gospodarza. Pozostałe warunki (limit dwóch graczy, zgodność buildu, ten
    sam gracz po obu stronach, poprawny pseudonim i indeks drużyny) działają
    bez zmian.
  • Wybór drużyny w lobby (MultiplayerMenu) przewija pełną listę reprezentacji
    dla obu stron — żadna nie jest pomijana dlatego, że wziął ją przeciwnik.
    Dołączenie do pokoju z listy nie przestawia już po cichu drużyny gracza.
  • GameplayBuildUuid podbite, bo starszy gospodarz nadal odrzucałby gościa,
    któremu nowy klient pozwala wybrać tę samą drużynę.

Pełna rozdzielczość i wygładzanie na iPadzie oraz tvOS
------------------------------------------------------
23.07.2026, 19:06

  • Mobile_RPAsset renderuje w pełnej rozdzielczości (m_RenderScale z 0.8 na
    1). Profil obejmuje iOS, iPadOS i tvOS, więc gra rysowała się dotąd w 80%
    rozdzielczości ekranu i była skalowana w górę — na iPadzie Pro i Apple TV
    4K widoczne jako miękki, nieostry obraz. Przy tej skali sceny nie ma
    powodu, żeby oszczędzać na wypełnieniu.
  • Wygładzanie krawędzi w profilu mobilnym podniesione z MSAA 2x na 4x. Na
    układach graficznych Apple (TBDR) MSAA rozwiązywane jest w pamięci kafla,
    więc koszt jest niski, a skośne krawędzie planszy i figurek wyraźnie na
    tym zyskują.
  • Poziom jakości Mobile używa czterech wag kości zamiast dwóch
    (skinWeights), co wygładza deformację modeli zawodników i bramkarza w
    bliskim widoku 3D, oraz wymusza filtrowanie anizotropowe
    (anisotropicTextures), przez co murawa i blat pozostają ostre przy płaskim
    kącie kamery.
  • antiAliasing w poziomie jakości Mobile ustawione na 4, zgodnie z profilem
    URP. W URP o wygładzaniu decyduje asset potoku, więc pole to jedynie
    przestaje przeczyć faktycznemu ustawieniu.
  • Ustawienia cieni w profilu mobilnym zostają bez zmian: mapa 2048 px,
    zasięg 36 jednostek i jedna kaskada to celowy wybór z wpisu „Jasne figurki
    i stabilne stadionowe cienie", skupiający rozdzielczość cienia na planszy.
    Podniesienie ich do wartości z profilu PC cofnęłoby tamtą poprawkę
    migotania na iPadzie Pro.
  • lodBias pozostaje bez zmian, ponieważ projekt nie zawiera żadnego LODGroup
    — parametr nie ma tu na co działać.

Build tvOS i wybór platform w skrypcie wdrożenia
------------------------------------------------
23.07.2026, 19:03

  • Tools/build-and-deploy.sh eksportuje projekt Xcode dla tvOS do Build/tvOS
    jako krok 5, po iOS i po wysłaniu paczek desktopowych. Jak przy iOS skrypt
    nie uruchamia Xcode ani nie buduje .ipa — podpisywanie i provisioning
    zostają po stronie Xcode.
  • Build tvOS nie trafia do build-info.json, więc nie pojawia się na liście
    pobrań. Jego tożsamość ląduje na serwerze w osobnym pliku .tvos-build.json
    z tym samym UUID i czasem builda co reszta przebiegu.
  • Skrypt przyjmuje --only i --skip z listą platform po przecinku (macos,
    windows, ios, tvos). Bez tych flag budowane jest wszystko, czyli normalny
    przebieg wydania. Nieznana nazwa platformy przerywa działanie z
    komunikatem zamiast po cichu nie zbudować niczego.
  • build-info.json powstaje wyłącznie z platform faktycznie zbudowanych w
    danym przebiegu; wcześniej lista była zapisana na sztywno, więc zawężony
    build wypisywałby niepoprawny JSON z pustym rozmiarem.
  • Przy zawężonym przebiegu skrypt wysyła zbudowane paczki, ale nie nadpisuje
    .build-info.json ani .changelog.json na serwerze. Metadane opisują całą
    listę pobrań, więc częściowy build usunąłby z niej platformy, których
    akurat nie budowano.
  • tvOS ma własny identyfikator aplikacji tech.adamczyk.TacticsFootball w
    ProjectSettings.asset. Wcześniej applicationIdentifier miał wpisy tylko
    dla Android, Standalone i iPhone, mimo włączonego
    overrideDefaultApplicationIdentifier, więc świeżo dodana platforma nie
    miała ustawionego bundle ID.
  • Wyeksportowane projekty Xcode dostają nazwy
    TacticsFootball-iPadOS.xcodeproj i TacticsFootball-tvOS.xcodeproj. Unity
    nadaje każdemu eksportowi Apple nazwę Unity-iPhone.xcodeproj, także dla
    tvOS, przez co oba projekty były nie do odróżnienia na liście ostatnio
    otwieranych w Xcode. Zmieniana jest wyłącznie nazwa pakietu projektu —
    target i schemat w środku pozostają Unity-iPhone, bo ich przepisywanie
    oznaczałoby ingerencję w wygenerowany pbxproj bez realnego zysku. Krok
    jest bezpieczny, ponieważ każdy przebieg czyści Build/ i eksportuje od
    zera, więc Unity nigdy nie szuka tego projektu ponownie.
  • Krok iOS nazywa się w wyjściu skryptu „iPadOS", zgodnie z targetDevice: 1
    w ustawieniach gracza — build jest przeznaczony wyłącznie na iPada.

Motywy meczowe Anglii, Belgii i Szwajcarii
------------------------------------------
23.07.2026, 18:51

  • Do Assets/Resources/Audio trafiły trzy nowe motywy meczowe: England.ogg,
    Belgium.ogg i Switzerland.ogg. Nazwy odpowiadają wartościom NationalTeam,
    więc MatchAudio.LoadNationTheme podpina je automatycznie — bez zmian w
    kodzie. Plik dostarczony jako Swiss.mp3 nosi nazwę Switzerland, bo
    poprzednia nie pasowała do enuma i motyw nigdy by się nie wczytał.
  • Materiał źródłowy był w MP3, więc został przekodowany na Ogg Vorbis (-q:a
    5, 44,1 kHz, stereo), tak jak reszta katalogu. Cały folder ma dzięki temu
    jeden format, a MP3 nie zostaje w repozytorium — Unity i tak kompresuje
    wszystko do Vorbisa, więc trzymanie źródeł w MP3 oznaczałoby kodowanie
    stratne dwa razy pod rząd.
  • Nowe pliki mają własne .meta z takimi samymi ustawieniami importu jak
    dotychczasowe motywy (streaming, Vorbis, bez wstępnego wczytywania), żeby
    import w Unity nie ustawiał ich domyślnie na dekompresję do pamięci.
  • Bez motywu pozostaje już tylko Portugalia — dla niej nadal gra wspólny
    temat zapasowy.

Nieudane przyjęcie po wykopie bramkarza
---------------------------------------
23.07.2026, 15:46

  • Daleki wykop bramkarza, który nie dochodzi, ale kończy się najwyżej dwa
    pola od odbiorcy i nikt go nie przejmuje, jest teraz pokazywany jako
    nieudane przyjęcie: piłka leci pełnym łukiem na odbiorcę, odbija mu się od
    głowy i dopiero potem spada na pole luźnej piłki. Warunek rozpoznaje
    MatchController.IsHeadBounceMiss, lot obsługuje
    BallView.AnimateHeadBounceTo, a odbiorca odchyla głowę w momencie kontaktu
    (PlayerView.PlayHeadBounce) i po wyprostowaniu kręci nią z
    niezadowoleniem.
  • Punkt kontaktu z głową bierze się z animowanej kości
    (PlayerView.HeadContactPosition), więc piłka trafia w czubek głowy także
    wtedy, gdy zawodnik się porusza.
  • Przy takim odbiciu bramkarz nie kręci już głową jak po zepsutym podaniu —
    błąd jest po stronie odbiorcy — a podpowiedź w HUD brzmi „Odbiorca nie
    przyjął piłki — luźna piłka.".
  • Komentarz meczowy ma osobną pulę zdań na nieudane przyjęcie po wykopie
    (MatchCommentary.Pass z receiverMiscontrol), a dodatkowe zdanie
    klimatyczne dotyczy odbiorcy, nie podającego: nowy moment
    CommentaryMoment.BadTouch ma teksty dla wszystkich czternastu
    reprezentacji oraz dla obrońcy, pomocnika i napastnika.
  • Rozpoczęcie meczu dostaje drugie zdanie w barwach reprezentacji
    rozpoczynającej (CommentaryMoment.KickOff, MatchCommentary.KickOff(nazwa,
    drużyna)). Zdania są dobierane przez TeamFlavour, bo w tym momencie nie ma
    jeszcze zawodnika, do którego można by przypiąć klimat.
  • To samo zachowanie działa w turze komputera, więc wykop bramkarza AI
    wygląda i brzmi tak samo jak wykop gracza.
  • UUID buildu klienta podbity na 6f3b9c21-5d84-4a17-9c2e-7b1d0a48e935, bo
    zmieniają się animacje.

Lob tylko nad wychodzącym bramkarzem
------------------------------------
23.07.2026, 15:34

  • Lob wymaga teraz ustawienia bramka → bramkarz → strzelec: strzelec musi
    stać dalej od atakowanej linii końcowej niż bramkarz od własnej. Gdy
    napastnik minął już bramkarza, nie ma nad kim przerzucać piłki, więc akcja
    jest niedostępna niezależnie od dystansu między nimi.
  • Nowy powód odrzucenia ShotRejection.KeeperNotAheadOfShooter i pomocnicza
    DistanceFromAttackedGoalLine. Pozostałe warunki loba (umiejętność strzału,
    bramkarz min. 2 pola przed linią, maks. 2 pola od strzelca) bez zmian.
  • Podpowiedź przy niedostępnym lobie wymienia komplet warunków, łącznie z
    nowym.
  • UUID buildu klienta podbity na ad4f1d3b-6563-467b-8e38-1fb4078206a8, bo
    zmieniają się reguły rozgrywki.

Menu akcji przy karcie zawodnika i panel pojedynku
--------------------------------------------------
23.07.2026, 14:52

  • Panel akcji stoi teraz w lewym dolnym rogu, dosunięty do prawej krawędzi
    karty zawodnika i wyrównany do jej dolnej linii, zamiast po przeciwnej
    stronie ekranu. Karta, panel i pasek komentarza tworzą jeden blok.
  • Panel nie ma już nagłówka „AKCJE" ani linii nagłówkowych. Zamiast tego ma
    na górze pasek w barwie aktywnej drużyny, tak samo jak karta zawodnika.
  • Przyciski są węższe, niższe i układają się w listę od góry panelu, a panel
    dopasowuje wysokość do liczby widocznych akcji. Wcześniej stos był
    wyśrodkowany w panelu o stałej wysokości.
  • Przyciski akcji rysują się nową, płaską gęstością RetroButtonDensity.Flat:
    jednolite wypełnienie, jedna cienka jaśniejsza ramka, bez fazowania i bez
    zaokrągleń. Etykiety w menu akcji są zawsze pogrubionym JetBrains Mono,
    także gdy nie zawierają cyfr.
  • Kolejność akcji od góry: podanie, strzał, odbiór, lob, cofnij ruch,
    zakończ turę. Zestaw akcji bez zmian.
  • Kolory wariantów przycisków (zielony, złoty, czerwony, niebieski,
    neutralny) pozostają bez zmian, poza przyciskami niosącymi szansę — te
    malują się dokładnie kolorem znacznika z boiska.
  • Przyciski potwierdzenia i anulowania korzystają z tego samego układu listy
    co pozostałe akcje, a gdy widoczny jest panel pojedynku, przenoszą się do
    jego stopki.
  • Akcje rozstrzygane między dwoma zawodnikami pokazują panel pojedynku nad
    paskiem komentarza — pasek dokładnie tak wysoki jak portret (124
    jednostki). Każda strona to portret, nazwisko, metryczka i jeden pasek: ta
    umiejętność, o którą dana akcja faktycznie się rozgrywa. Podanie zestawia
    podanie podającego z przyjęciem odbiorcy, odbiór obronę odbierającego z
    kontrolą zawodnika z piłką, a strzał i lob strzał napastnika z
    interwencjami bramkarza. W kolumnie środkowej „VS" stoi w linii nazwisk,
    pod nim wartość szansy, a pod nią rodzaj zagrania. Przyciski potwierdzenia
    i anulowania wiszą pod płytą panelu, poza jego tłem.
  • Karta wybranego zawodnika chowa się na czas panelu pojedynku, bo panel
    niesie tę samą kartę po lewej stronie.
  • Szansa jest wszędzie w tym samym kolorze co znacznik na murawie: wartość w
    panelu pojedynku, przycisk potwierdzenia i przycisk „ODBIÓR • %" w liście
    akcji. Podanie i strzał biorą BoardView.SuccessChanceColor/GoalAimColor,
    odbiór osobną paletę TackleChanceColor, w której najmocniejsza próba jest
    czerwona.
  • UiSupport.ApplyTintedFlatButton maluje płaski przycisk dowolnym kolorem:
    sprite jest szary (jaśniejsza ramka, ciemniejsze lico), a barwę niesie
    Image.color, więc przycisk trafia w kolor boiska co do wartości zamiast
    wybierać najbliższy wariant. Kolor etykiety dobiera się z jasności
    wypełnienia. Progowe ConfirmVariant zostało usunięte.
  • Etykiety przycisków rozwijanego menu meczu i okna potwierdzenia
    zakończenia meczu są pisane JetBrains Mono, tak jak lista akcji.
  • Tła paneli menu obejmują całą zawartość: panel menu podniesiono z 200 do
    218 jednostek, a blok kamery ze 112 do 124, bo dolne przyciski wystawały
    poza ciemne tło.
  • Panel pojedynku znika w chwili naciśnięcia „Potwierdź" albo „Anuluj", a
    nie dopiero po rozegraniu akcji, więc nie zasłania boiska, gdy piłka jest
    w powietrzu.
  • Odbiór ma teraz krok potwierdzenia (tryb TackleAiming) zamiast
    natychmiastowego wykonania po kliknięciu przycisku. Kliknięcia na boisku w
    tym trybie są ignorowane, „Anuluj" wraca do wyboru akcji.
  • Mapowanie czterech pasków umiejętności zawodnika jest wspólne dla karty i
    panelu pojedynku (SkillRowsFor).
  • Wszystkie przyciski w stylu retro (HUD, menu, lobby, historia) reagują na
    kursor: RetroButtonHover rozjaśnia je nakładką z tego samego kafelkowanego
    sprite'a i lekko powiększa, a wciśnięcie przygasza ruch i mocniej
    rozjaśnia. Nieaktywny przycisk nie podświetla się, nawet jeśli kursor stoi
    na nim w chwili zablokowania akcji. Wcześniejsze highlightedColor nie
    działało, bo przyciski rysują się pełną bielą, a mnożnik powyżej 1 jest
    ucinany przy pakowaniu koloru wierzchołka.
  • Rozwijane menu meczu jest wypłaszczone tak samo jak lista akcji: przycisk
    „MENU", przyciski kamery, „ZAKOŃCZ MECZ", „WRÓĆ DO GRY" i przyciski w
    oknie potwierdzenia zakończenia meczu rysują się gęstością Flat, bez
    fazowania i zaokrągleń, oraz są niższe. Siatka przycisków kamery ma równy
    odstęp 4 jednostek między rzędami, a panel menu skrócono z 230 do 200
    jednostek. Ekrany po meczu i po utracie połączenia zachowują dawną,
    wypukłą ramkę.

Poprawny Team ID podpisywania iOS
---------------------------------
23.07.2026, 11:11

  Poprawki:
  • Ustawienia gracza dla iOS zawierają teraz właściwy identyfikator zespołu
    Apple (8T8U5R5V6P) zamiast identyfikatora certyfikatu podpisującego, przez
    co generowany projekt Xcode nie kończył się już błędami „No Account for
    Team" i brakiem profilu provisioningu dla pl.siano.tacticsfootball.

Czytelny numer i spokojna bluza bramkarza
-----------------------------------------
23.07.2026, 09:31

  • Numer na plecach bramkarza jest odsuwany od zmierzonej powierzchni pleców
    o 3,5 cm zamiast 1,2 cm, bo luźna bluza wybrzusza się poza najdalszy
    próbkowany wierzchołek. Numery zawodników z pola pozostają bez zmian.
  • Materiał bluzy bramkarza jest skonfigurowany tak samo jak rękawice: mapa
    materiału jako barwione albedo przy tym samym kafelkowaniu, bez mapy
    normalnych.
  • Numer na plecach jest rysowany materiałem z własnego shadera
    RuntimeTransparent (alpha blending) zamiast przycinanego alfą URP/Unlit.
    Nieużywana już MaterialFactory.TexturedUnlitCutout została usunięta.
  • UUID buildu klienta podbity na 1975b9bb-6f2e-4997-8b0c-82fad92c2de0, żeby
    sprawdzić mechanizm wymuszania aktualizacji.

  Poprawki:
  • Bluza bramkarza nie obcina już boków cyfr na jego numerze.
  • Na iOS wokół numerów nie ma już czarnych plakietek: przezroczyste tło
    łatki było przycinane słowem kluczowym _ALPHATEST_ON, a że materiał
    powstaje w runtime, wariant shadera był usuwany przy budowaniu playera i
    tło renderowało się jako pełna czerń.
  • Bluza bramkarza nie pokazuje już rozmazanych, pionowych smug: pochodziły z
    mapy normalnych wyliczanej w locie z niemal płaskiej tekstury plasteliny,
    ze wzmocnieniem szumu 12×. Ta mapa została usunięta.

Jasne figurki i stabilne stadionowe cienie
------------------------------------------
23.07.2026, 08:05

  • Dominujące ciepłe światło kierunkowe zapewnia krótki, czytelny miękki cień
    zawodników, bramek, piłki i planszy na każdym profilu renderowania.
  • Cztery słabsze reflektory obejmują boisko z przeciwnych narożników, ale
    nie generują osobnych map cieni; jeden kierunkowy cień pozostaje czytelny,
    stabilny i niezależny od wypełnienia murawy oraz stołu.
  • Materiały figurek mają wyraźne, zgodne z ich kolorem i fakturą wypełnienie
    emisyjne, które utrzymuje czytelne stroje, skórę i twarze z każdej strony
    także w bliskim widoku 3D bez rozjaśniania boiska ani osłabiania rzucanego
    cienia; ciemne barwy dostają pełną siłę wypełnienia, a jasne automatycznie
    ograniczoną, aby białe stroje się nie przepalały.
  • Piłka jawnie rzuca i odbiera cienie, a obniżony bias świateł zachowuje jej
    mały cień kontaktowy na murawie zamiast odcinać go jako detal mniejszy od
    ustawionej korekty.
  • Mobilny profil URP używa mapy głównego cienia 2048 px, miękkiego
    filtrowania oraz zasięgu 36 jednostek przy jednej stabilnej kaskadzie,
    skupiając rozdzielczość na planszy zamiast na niewidocznym otoczeniu.

  Poprawki:
  • Cienie nie znikają już całkowicie, gdy aktywny renderer pomija mapy cieni
    świateł dodatkowych, ponieważ gwarantowany cień pochodzi ze światła
    głównego URP.
  • W izometrii główne światło utrzymuje ukośny kierunek względem ekranu, więc
    cień nie chowa się bezpośrednio za figurką; w top-down i niskim 3D używa
    stałego kierunku świata i nie obraca się razem z kamerą ani śledzoną
    akcją.
  • Granatowe stroje oraz ciemniejsze odcienie skóry nie zapadają już w niemal
    czarne sylwetki po obróceniu niskiej kamery 3D na stronę odwróconą od
    głównego światła.
  • Cienie na urządzeniach iOS, w tym iPadzie Pro, nie korzystają już z
    twardej mapy 1024 px rozciągniętej na nadmierny zasięg 50 jednostek, co
    ogranicza poszarpane krawędzie i migotanie przy ruchu kamery.

Dedykowany model i animacje GK Paruwa
-------------------------------------
22.07.2026, 20:36

  • Bramkarze używają wyłącznie dedykowanego modelu GK_Paruwa, podczas gdy
    zawodnicy z pola zachowują dotychczasowy model parówczaka.
  • Jeden asset FBX bramkarza zawiera siatkę, rig Humanoid, 22 animacje
    bramkarskie z paczki oraz Happy Idle; animacje zawodników z pola nie są do
    niego dołączane.
  • Akcje meczowe korzystają z klipów osadzonych w tym samym FBX: parady
    wybierają Goalkeeper Diving Save lub Goalkeeper Diving Save 2 według
    strony strzału, krótkie podania poniżej czterech pól — także poniżej
    trzech — sprowadzają piłkę z dłoni pod dominującą stopę, używają
    Goalkeeper Pass po ziemi i są tak nazwane po wskazaniu odbiorcy, a ruch w
    obie strony wzdłuż własnej linii bramkowej używa wariantów Goalkeeper
    Sidestep bez obracania bramkarza bokiem do boiska.
  • Po dojściu do leżącej luźno piłki na polu własnego pola karnego bramkarz
    podnosi ją animacją Goalkeeper Catch; poza polem karnym przejęcie nie
    uruchamia chwytu rękami. Złapany centralny strzał używa Goalkeeper Catch
    2, natomiast złapany lob lub strzał w górny róg — Goalkeeper Catch 4; tor
    piłki śledzi środek animowanych rękawic także podczas chwytu wysokiej
    piłki.
  • Przy paradzie pełna sylwetka przemieszcza się z pola bramkarza na wolne
    pole sąsiednie w kierunku strzału, faktycznie kładzie się na murawie
    zgodnie z najniższym punktem animowanego modelu, przez chwilę pozostaje w
    miejscu lądowania i wraca podczas fazy podnoszenia; wybór pola wyklucza
    komórkę piłki oraz innych zawodników. Przy udanej obronie tor strzału
    nadal śledzi animowaną dłoń, więc widoczny kontakt wypada na rękawicy.
  • Przy posiadaniu piłki całe ciało nadal zapętla osadzony klip Happy Idle, a
    obie ręce są nakładane na tę animację dwuczłonowym solverem wokół boków
    piłki; jej środek wynika z powierzchni poruszających się rękawic i jest
    ograniczony przed tułowiem, więc bramkarz swobodnie się buja bez
    odklejania chwytu, przenikania ani niedeterministycznej fizyki Rigidbody.
  • Poza gry w spoczynku ma szerzej opuszczone ręce i czytelne rękawice
    zamiast dłoni schowanych przy tułowiu.
  • Każdy z 14 bramkarzy ma własną paletę bluzy i dołu zgodną z jego dużym
    portretem: m.in. czerwony Donnarumma, zielony Pickford, niemal czarny
    Nyland, żółci Simón i Courtois, pomarańczowy Maignan oraz złoty Ochoa;
    jedna centralna mapa stosuje te same barwy w zestawie domowym i
    wyjazdowym, zachowując jasne rękawice i skarpety oraz czarne buty,
    kołnierz i mankiety.
  • Dolna krawędź bluzy bramkarza sięga do samej nasady nóg: końcowe poziome
    nadpisanie materiału obejmuje zarówno miednicę, jak i górny pas
    wierzchołków ważonych do nóg, usuwając cały cielisty pas i zachowując
    płaski brzeg.
  • Oczy GK Paruwa oraz numer korzystają z osi kierunku PlayerModel, a nie
    obróconej osi importowanego FBX, dlatego trafiają odpowiednio na widoczny
    przód głowy i tył bluzy. Oczy są zbudowane jak u zawodników z pola z
    osobnej białkówki, tęczówki i źrenicy, ale każda warstwa jest niemal
    płaska i dopasowana do krzywizny głowy; numer używa dokładnie tej samej
    wypiekanej łaty i kroju cyfr co koszulki zawodników z pola, lecz wspólny
    materiał numerów działa jako alpha-cutout zapisujący głębokość zamiast
    zawodnego alpha-blendu.
  • Materiały GK Paruwa odwzorowują ręcznie lepiony charakter referencji:
    skóra zachowuje drobne ziarno osłonki, bluza, kołnierz i mankiety używają
    neutralnej faktury modeliny, wyższe getry oraz rękawice mają grubą
    wełnianą dzianinę, a czarne buty drobne ziarno skóry. Mapy są tintowane w
    runtime, więc indywidualne kolory strojów reprezentacji pozostają
    zachowane. Bluza używa teraz tak samo czytelnych ustawień jak wzmocniona
    wełna — projekcji UV 0–1, tilingu 0.9, smoothness 0.025 i mapy normalnej o
    sile 0.55 wyprowadzonej z własnej plastelinowej mapy — dzięki czemu relief
    pozostaje plastelinowy, ale nie znika na dużych płaskich fragmentach.
    Getry i każda kompletna rękawica otrzymują analogiczną projekcję względem
    kości łydki lub dłoni, bez osobnego rozciągania wzoru na palcach.
  • Generator assetu pozwala odtworzyć scalony FBX z paczki źródłowej i
    osobnego klipu Happy Idle, zachowując wyłącznie animacje bramkarza.
  • Testy edytora weryfikują liczbę i rodzaj klipów, osobny model Humanoid,
    rozstaw rąk, strefy materiałów, kolory reprezentacji, oczy oraz numer na
    plecach.
  • UUID zgodności klienta został zmieniony ze względu na nowy model, pozę i
    zestaw animacji bramkarza.

  Poprawki:
  • Oczy GK nie korzystają już z zawodnych przezroczystych nakładek, które
    istniały i reagowały na mruganie, lecz wizualnie zlewały się z materiałem
    modelu; nieprzezroczyste, spłaszczone warstwy zachowują pełny kontrast
    niezależnie od ścieżki renderowania.
  • Usunięty został osobny segmentowy generator numerów bramkarza, który
    rozsuwał komórki cyfr i potrafił pokazywać na plecach kształt
    przypominający inny, wielocyfrowy numer.
  • Łata numeru GK nie chowa się już pod grubszą, animowaną siatką bluzy:
    przed jej utworzeniem odczytywana jest aktualna powierzchnia skinned
    mesha, a niewielki odstęp oraz wycinający tło, nieprzezroczysty nadruk z
    zapisem głębokości utrzymują cyfrę widoczną bez odstawania od pleców.

Komplet portretów graczy według reprezentacji
---------------------------------------------
22.07.2026, 17:43

  • Portrety graczy są pogrupowane w folderach reprezentacji oraz wariantach
    Large i Small.
  • HUD wybiera najpierw duży portret konkretnego gracza, potem jego mały
    portret, a następnie dużą i małą parówkową zaślepkę.
  • Małe portrety zwykłych zawodników nie są już pomijane przez warunek
    przeznaczony dla gwiazd.
  • Każda reprezentacja ma duży i mały portret wszystkich czterech zawodników;
    42 zawodników niebędących gwiazdami otrzymało uproszczone, rozpoznawalne
    portrety parówczaków.
  • Portrety używają barw reprezentacji w tle i spójnych koszulek pola, a
    bramkarze mają odrębne stroje bramkarskie zgodne z paletą swojej drużyny.
  • Nazwy plików portretów zawierają wyłącznie znaki ASCII, a HUD
    automatycznie usuwa znaki diakrytyczne z nazwisk przy budowaniu ścieżki
    zasobu.
  • Pedri, Zieliński, Bruno Fernandes, Courtois, De Jong, Diogo Costa, Lukaku
    i Rúben Dias używają wydłużonej, uproszczonej sylwetki parówki spójnej z
    pozostałymi portretami niebędącymi gwiazdami.
  • Retegui jest przedstawiony bez pełnego zarostu, z charakterystycznymi
    jasnobrązowymi włosami zaczesanymi do tyłu i dłuższymi z tyłu.
  • Brahim Díaz ma młodzieńcze rysy, proste ciemnobrązowe włosy z dłuższą
    grzywką zaczesaną na bok, krótsze boki i równy subtelny zarost.

  Poprawki:
  • Portrety zawodników z diakrytyką w nazwisku, w tym Bruno Guimarãesa, są
    wczytywane zamiast ogólnej parówkowej zaślepki niezależnie od normalizacji
    nazw plików przez system operacyjny.

Widoczny postęp wysyłania paczek
--------------------------------
22.07.2026, 17:32

  • Wdrożenie pokazuje postęp każdej wysyłki zamiast milczeć przez
    kilkadziesiąt sekund: używa rsync z licznikiem procentowym, a gdy go brak,
    wraca do scp z jego własnym paskiem postępu.
  • Przy każdej paczce wypisywany jest jej rozmiar, więc widać, ile danych
    idzie na serwer.
  • Przerwana wysyłka może zostać wznowiona bez ponownego przesyłania całego
    pliku (--partial).

Paczka Windows budowana jako x86_64
-----------------------------------
22.07.2026, 17:20

  Poprawki:
  • Build Windows powstawał jako ARM64, ponieważ edytor na Apple Silicon
    ustawia taką architekturę dla playera Windows; opublikowana paczka nie
    uruchamiała się na typowych komputerach graczy.
  • Skrypt budowania wymusza architekturę x64 przed każdym buildem Windows,
    ustawiając UserBuildSettings.architecture rozszerzenia platformy Windows.
    Samo -buildTarget StandaloneWindows64 ani PlayerSettings.SetArchitecture
    nie mają na to wpływu.
  • Po zbudowaniu skrypt czyta nagłówek PE gotowego .exe i przerywa wdrożenie,
    gdy plik nie jest x86_64, więc zła architektura nie trafi już do
    dystrybucji.

Diagnostyka ekranu "Wymagana aktualizacja"
------------------------------------------
22.07.2026, 17:05

  • Ekran wymaganej aktualizacji pokazuje UUID protokołu oczekiwany przez grę,
    UUID zwrócony przez serwer oraz UUID i datę uruchomionej paczki, dzięki
    czemu widać, która strona jest nieaktualna.
  • Te same dane trafiają do logu gry, więc problem da się zdiagnozować także
    ze zdalnej maszyny.
  • Sprawdzenie zgodności rozróżnia teraz odpowiedź nieczytelną, odpowiedź bez
    UUID, odpowiedź z innym UUID oraz odmowę serwera (HTTP 426); wcześniej
    wszystkie te przypadki wyglądały identycznie.

Czytelna lista zmian w paczkach z grą
-------------------------------------
22.07.2026, 16:34

  • Paczki macOS i Windows zawierają LISTA ZMIAN.txt zamiast surowej kopii
    roboczego changelogu.
  • Plik dla graczy jest zwykłym tekstem: bez znaczników Markdown, bez
    odwrotnych apostrofów i bez sekcji Files, z zawijaniem wierszy i datą w
    formacie 22.07.2026, 14:53.
  • Wpisy są sortowane od najnowszego, niezależnie od kolejności w pliku
    roboczym.
  • Proces budowania generuje ten plik na starcie i przerywa build, jeśli
    konwersja się nie powiedzie.
  • Roboczy changelog używa pogrubionych nagłówków sekcji (Changed,
    opcjonalnie Fixed, Files) z pustą linią pod każdym, dzięki czemu podglądy
    Markdown renderują punkty listy zamiast zlewać je w akapit, a każdy plik
    stoi w osobnej linii.
  • Konwerter dla graczy rozumie oba warianty nagłówków i podpisuje sekcje
    inne niż Changed (Poprawki, Nowości, Usunięte).
  • Tools/sort-changelog.py przestawia wpisy roboczego changelogu od
    najnowszego do najstarszego bez zmiany ich treści; tryb --check tylko
    weryfikuje kolejność. Rozwiązuje to rozjeżdżanie się pliku, gdy kilka
    agentów wstawia wpisy równolegle.
  • Build sortuje changelog przed wygenerowaniem listy zmian dla graczy.
  • Wymagany format wpisu oraz obowiązek sortowania są opisane w instrukcjach
    projektu i w AGENTS.md.

Muzyka meczu tylko z motywu lokalnej drużyny
--------------------------------------------
22.07.2026, 16:09

  • Gdy drużyna gracza nie ma własnego motywu muzycznego, mecz gra domyślny
    motyw zamiast motywu przeciwnika (np. Anglia–Argentyna nie odtwarza już
    muzyki Argentyny).
  • Domyślny motyw meczu (Microprose Soccer Theme) jest ponownie odtwarzany: z
    pliku usunięto osadzony strumień wideo Theora, przez który Unity nie
    importowało go jako AudioClip.

Plastikowe wykończenie dolnych pasków HUD
-----------------------------------------
22.07.2026, 16:01

  • Dolny pasek wyniku ma subtelne modelowanie formowanego plastiku: szeroki,
    słaby refleks, delikatnie zaokrąglone cieniowanie i cienkie krawędzie bez
    emisji ani nadmiernego rozjaśnienia.
  • Niebieski pasek komentarza wygląda jak elegancko wpuszczony panel: ma
    ciemny miękki obrys, wewnętrzny cień przy górnej krawędzi i delikatnie
    oświetloną dolną wargę, bez nadmiernego połysku.

Planszowe otoczenie sceny meczu
-------------------------------
22.07.2026, 15:37

  • Istniejąca murawa jest automatycznie osadzana w jasnej, grubej obudowie z
    niską czteroczęściową ramą, bez zmiany hierarchii ani współrzędnych
    boiska, bramek i elementów rozgrywki.
  • Pod planszą znajduje się duży, gruby blat w kolorze ciepłego drewna, który
    w widoku izometrycznym i niskim 3D wypełnia przestrzeń wokół boiska.
  • Blat używa bezszwowej tekstury ciemnego orzecha włoskiego z naturalnym,
    spokojnym rysunkiem słojów i skalowaniem zachowującym stałą wielkość wzoru
    niezależnie od rozmiaru boiska.
  • Gruba podstawa planszy i jej czteroczęściowy rant używają bezszwowej
    faktury ciepłej porcelany oraz gładkiego, niemetalicznego szkliwa
    reagującego na reflektory sceny.
  • Wymiary obudowy, ramy i stołu wynikają z rzeczywistych rendererów Pitch i
    PitchApron; środowisko aktualizuje istniejące obiekty po nazwie i nie
    dodaje duplikatów przy ponownej konfiguracji.
  • Elementy otoczenia rzucają i odbierają cienie, nie mają colliderów, a
    stadionowe reflektory używają miękkich cieni uziemiających planszę na
    blacie.

Ping serwera i automatyczne odświeżanie listy gier
--------------------------------------------------
22.07.2026, 14:53

  • Nagłówek ekranu „GRA SIECIOWA” pokazuje ping do serwera lobby obok stanu
    połączenia (● POŁĄCZONO · 42 ms · SERWER EU), a kolor zmienia się wraz z
    opóźnieniem; przy błędzie sieci widnieje BRAK POŁĄCZENIA.
  • Ping mierzy osobne, minimalne zapytanie do /health (LobbyClient.Ping),
    więc pokazuje opóźnienie łącza, a nie koszt budowania listy gier.
  • Lista dostępnych pokoi odświeża się sama co 5 sekund, gdy gracz jest na
    ekranie wyboru gry sieciowej; w tym samym cyklu wykonywany jest pomiar
    pingu. Ręczny przycisk „ODŚWIEŻ LISTĘ” działa jak wcześniej.
  • Równoległe zapytania o listę są blokowane, a komunikat „Pobieranie listy
    gier” nie miga przy cyklicznym odświeżaniu.

Sprawdzanie dostępnej aktualizacji gry
--------------------------------------
22.07.2026, 14:50

  • Skrypt budujący stempluje klienta identyfikatorem wydania
    (Assets/Resources/build-id.txt), tym samym, który trafia do metadanych
    serwera i archiwów.
  • Gra po wejściu do menu głównego pyta /v1/downloads o build opublikowany
    dla swojej platformy.
  • Modal „DOSTĘPNA NOWA WERSJA” z przyciskami ANULUJ i POBIERZ pojawia się,
    gdy identyfikator opublikowanego wydania różni się od lokalnego — w obie
    strony, bez porównywania czasu budowania. POBIERZ otwiera stronę
    pobierania.
  • Build bez stempla (wydania sprzed wprowadzenia stemplowania) traktowany
    jest jako nieaktualny i również dostaje monit.
  • Modal pokazuje się raz na uruchomienie gry — powrót z meczu do menu go nie
    przywraca.
  • Sprawdzenie pomija wyłącznie edytor Unity; błędy sieci są ciche i niczego
    nie blokują.
  • Sprawdzenie jest niezależne od serverProtocolUUID i GameplayBuildUuid —
    dotyczy wydania, nie zgodności protokołu.
  • Metadane buildu zawierają wpis ios z pustą ścieżką: paczka nie jest
    wgrywana, ale wpis niesie identyfikator wydania, więc iOS też wykrywa
    nieaktualną wersję.
  • /v1/downloads zwraca wpisy bez filename dla platform zadeklarowanych bez
    paczki, a nadal pomija te, których archiwum miało trafić na dysk i nie
    trafiło.
  • Na platformie bez paczki monit nie ma przycisku POBIERZ ani rozmiaru pliku
    — zostaje wyśrodkowany ZAMKNIJ.
  • Zakładka POBIERZ na stronie statystyk pomija wpisy bez pliku, więc iOS nie
    pojawia się tam jako drugi macOS z rozmiarem 0 MB i martwym przyciskiem.
  • Treść monitu używa fontu monospace, bo font dekoracyjny rysuje cyfry i
    interpunkcję jako znaki zastępcze.
  • README serwera opisuje endpointy lobby (/health, /v1/games, heartbeat,
    usuwanie, font) oraz /v1/downloads wraz z zasadą porównywania wersji i
    traktowaniem platform bez paczki.

Reakcje na pobliską luźną piłkę
-------------------------------
22.07.2026, 10:32

  • Zawodnicy, którzy mogą dojść do luźnej piłki w zasięgu czterech pól,
    patrzą na nią większymi oczami i niecierpliwie kiwają głową.
  • Zawodnicy poza zasięgiem ruchu nadal obracają się w stronę luźnej piłki,
    ale utrzymują wzrok na wprost zamiast spoglądać pod nogi.
  • Zmieniono UUID klienta, ponieważ animacje prezentacji meczu muszą być
    zgodne w rozgrywkach sieciowych.

Wspólne instrukcje agentów, UUID i changelog w paczkach
-------------------------------------------------------
22.07.2026, 09:32

  • Wspólne instrukcje dla Codexa i Claude określają prowadzenie roboczego
    changelogu znaczących zmian.
  • Instrukcje projektu określają, kiedy podbijać UUID serwera i klienta.
  • Sekcja Files w changelogu nie uwzględnia pliku CHANGELOG-DEV.md.
  • Proces pakowania dołącza aktualny changelog jako CHANGELOG.md do paczek
    macOS i Windows.
  • Build wymaga istniejącego pliku źródłowego changelogu przed uruchomieniem
    Unity.
